/[cvs]/jsr166/src/test/tck/TimeUnitTest.java
ViewVC logotype

Contents of /jsr166/src/test/tck/TimeUnitTest.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.31 - (show annotations)
Sat May 13 23:50:00 2017 UTC (2 years, 3 months ago) by jsr166
Branch: MAIN
Changes since 1.30: +3 -3 lines
claw back some millis using assertThreadBlocks

1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain, as explained at
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 * Other contributors include Andrew Wright, Jeffrey Hayes,
6 * Pat Fisher, Mike Judd.
7 */
8
9 import static java.util.concurrent.TimeUnit.DAYS;
10 import static java.util.concurrent.TimeUnit.HOURS;
11 import static java.util.concurrent.TimeUnit.MICROSECONDS;
12 import static java.util.concurrent.TimeUnit.MILLISECONDS;
13 import static java.util.concurrent.TimeUnit.MINUTES;
14 import static java.util.concurrent.TimeUnit.NANOSECONDS;
15 import static java.util.concurrent.TimeUnit.SECONDS;
16
17 import java.util.concurrent.CountDownLatch;
18 import java.util.concurrent.TimeUnit;
19
20 import junit.framework.Test;
21 import junit.framework.TestSuite;
22
23 public class TimeUnitTest extends JSR166TestCase {
24 public static void main(String[] args) {
25 main(suite(), args);
26 }
27
28 public static Test suite() {
29 return new TestSuite(TimeUnitTest.class);
30 }
31
32 // (loops to 88888 check increments at all time divisions.)
33
34 /**
35 * convert correctly converts sample values across the units
36 */
37 public void testConvert() {
38 for (long t = 0; t < 88888; ++t) {
39 assertEquals(t*60*60*24,
40 SECONDS.convert(t, DAYS));
41 assertEquals(t*60*60,
42 SECONDS.convert(t, HOURS));
43 assertEquals(t*60,
44 SECONDS.convert(t, MINUTES));
45 assertEquals(t,
46 SECONDS.convert(t, SECONDS));
47 assertEquals(t,
48 SECONDS.convert(1000L*t, MILLISECONDS));
49 assertEquals(t,
50 SECONDS.convert(1000000L*t, MICROSECONDS));
51 assertEquals(t,
52 SECONDS.convert(1000000000L*t, NANOSECONDS));
53
54 assertEquals(1000L*t*60*60*24,
55 MILLISECONDS.convert(t, DAYS));
56 assertEquals(1000L*t*60*60,
57 MILLISECONDS.convert(t, HOURS));
58 assertEquals(1000L*t*60,
59 MILLISECONDS.convert(t, MINUTES));
60 assertEquals(1000L*t,
61 MILLISECONDS.convert(t, SECONDS));
62 assertEquals(t,
63 MILLISECONDS.convert(t, MILLISECONDS));
64 assertEquals(t,
65 MILLISECONDS.convert(1000L*t, MICROSECONDS));
66 assertEquals(t,
67 MILLISECONDS.convert(1000000L*t, NANOSECONDS));
68
69 assertEquals(1000000L*t*60*60*24,
70 MICROSECONDS.convert(t, DAYS));
71 assertEquals(1000000L*t*60*60,
72 MICROSECONDS.convert(t, HOURS));
73 assertEquals(1000000L*t*60,
74 MICROSECONDS.convert(t, MINUTES));
75 assertEquals(1000000L*t,
76 MICROSECONDS.convert(t, SECONDS));
77 assertEquals(1000L*t,
78 MICROSECONDS.convert(t, MILLISECONDS));
79 assertEquals(t,
80 MICROSECONDS.convert(t, MICROSECONDS));
81 assertEquals(t,
82 MICROSECONDS.convert(1000L*t, NANOSECONDS));
83
84 assertEquals(1000000000L*t*60*60*24,
85 NANOSECONDS.convert(t, DAYS));
86 assertEquals(1000000000L*t*60*60,
87 NANOSECONDS.convert(t, HOURS));
88 assertEquals(1000000000L*t*60,
89 NANOSECONDS.convert(t, MINUTES));
90 assertEquals(1000000000L*t,
91 NANOSECONDS.convert(t, SECONDS));
92 assertEquals(1000000L*t,
93 NANOSECONDS.convert(t, MILLISECONDS));
94 assertEquals(1000L*t,
95 NANOSECONDS.convert(t, MICROSECONDS));
96 assertEquals(t,
97 NANOSECONDS.convert(t, NANOSECONDS));
98 }
99
100 for (TimeUnit x : TimeUnit.values()) {
101 long[] zs = {
102 0, 1, -1,
103 Integer.MAX_VALUE, Integer.MIN_VALUE,
104 Long.MAX_VALUE, Long.MIN_VALUE,
105 };
106 for (long z : zs) assertEquals(z, x.convert(z, x));
107 }
108 }
109
110 /**
111 * toNanos correctly converts sample values in different units to
112 * nanoseconds
113 */
114 public void testToNanos() {
115 for (long t = 0; t < 88888; ++t) {
116 assertEquals(t*1000000000L*60*60*24,
117 DAYS.toNanos(t));
118 assertEquals(t*1000000000L*60*60,
119 HOURS.toNanos(t));
120 assertEquals(t*1000000000L*60,
121 MINUTES.toNanos(t));
122 assertEquals(1000000000L*t,
123 SECONDS.toNanos(t));
124 assertEquals(1000000L*t,
125 MILLISECONDS.toNanos(t));
126 assertEquals(1000L*t,
127 MICROSECONDS.toNanos(t));
128 assertEquals(t,
129 NANOSECONDS.toNanos(t));
130 }
131 }
132
133 /**
134 * toMicros correctly converts sample values in different units to
135 * microseconds
136 */
137 public void testToMicros() {
138 for (long t = 0; t < 88888; ++t) {
139 assertEquals(t*1000000L*60*60*24,
140 DAYS.toMicros(t));
141 assertEquals(t*1000000L*60*60,
142 HOURS.toMicros(t));
143 assertEquals(t*1000000L*60,
144 MINUTES.toMicros(t));
145 assertEquals(1000000L*t,
146 SECONDS.toMicros(t));
147 assertEquals(1000L*t,
148 MILLISECONDS.toMicros(t));
149 assertEquals(t,
150 MICROSECONDS.toMicros(t));
151 assertEquals(t,
152 NANOSECONDS.toMicros(t*1000L));
153 }
154 }
155
156 /**
157 * toMillis correctly converts sample values in different units to
158 * milliseconds
159 */
160 public void testToMillis() {
161 for (long t = 0; t < 88888; ++t) {
162 assertEquals(t*1000L*60*60*24,
163 DAYS.toMillis(t));
164 assertEquals(t*1000L*60*60,
165 HOURS.toMillis(t));
166 assertEquals(t*1000L*60,
167 MINUTES.toMillis(t));
168 assertEquals(1000L*t,
169 SECONDS.toMillis(t));
170 assertEquals(t,
171 MILLISECONDS.toMillis(t));
172 assertEquals(t,
173 MICROSECONDS.toMillis(t*1000L));
174 assertEquals(t,
175 NANOSECONDS.toMillis(t*1000000L));
176 }
177 }
178
179 /**
180 * toSeconds correctly converts sample values in different units to
181 * seconds
182 */
183 public void testToSeconds() {
184 for (long t = 0; t < 88888; ++t) {
185 assertEquals(t*60*60*24,
186 DAYS.toSeconds(t));
187 assertEquals(t*60*60,
188 HOURS.toSeconds(t));
189 assertEquals(t*60,
190 MINUTES.toSeconds(t));
191 assertEquals(t,
192 SECONDS.toSeconds(t));
193 assertEquals(t,
194 MILLISECONDS.toSeconds(t*1000L));
195 assertEquals(t,
196 MICROSECONDS.toSeconds(t*1000000L));
197 assertEquals(t,
198 NANOSECONDS.toSeconds(t*1000000000L));
199 }
200 }
201
202 /**
203 * toMinutes correctly converts sample values in different units to
204 * minutes
205 */
206 public void testToMinutes() {
207 for (long t = 0; t < 88888; ++t) {
208 assertEquals(t*60*24,
209 DAYS.toMinutes(t));
210 assertEquals(t*60,
211 HOURS.toMinutes(t));
212 assertEquals(t,
213 MINUTES.toMinutes(t));
214 assertEquals(t,
215 SECONDS.toMinutes(t*60));
216 assertEquals(t,
217 MILLISECONDS.toMinutes(t*1000L*60));
218 assertEquals(t,
219 MICROSECONDS.toMinutes(t*1000000L*60));
220 assertEquals(t,
221 NANOSECONDS.toMinutes(t*1000000000L*60));
222 }
223 }
224
225 /**
226 * toHours correctly converts sample values in different units to
227 * hours
228 */
229 public void testToHours() {
230 for (long t = 0; t < 88888; ++t) {
231 assertEquals(t*24,
232 DAYS.toHours(t));
233 assertEquals(t,
234 HOURS.toHours(t));
235 assertEquals(t,
236 MINUTES.toHours(t*60));
237 assertEquals(t,
238 SECONDS.toHours(t*60*60));
239 assertEquals(t,
240 MILLISECONDS.toHours(t*1000L*60*60));
241 assertEquals(t,
242 MICROSECONDS.toHours(t*1000000L*60*60));
243 assertEquals(t,
244 NANOSECONDS.toHours(t*1000000000L*60*60));
245 }
246 }
247
248 /**
249 * toDays correctly converts sample values in different units to
250 * days
251 */
252 public void testToDays() {
253 for (long t = 0; t < 88888; ++t) {
254 assertEquals(t,
255 DAYS.toDays(t));
256 assertEquals(t,
257 HOURS.toDays(t*24));
258 assertEquals(t,
259 MINUTES.toDays(t*60*24));
260 assertEquals(t,
261 SECONDS.toDays(t*60*60*24));
262 assertEquals(t,
263 MILLISECONDS.toDays(t*1000L*60*60*24));
264 assertEquals(t,
265 MICROSECONDS.toDays(t*1000000L*60*60*24));
266 assertEquals(t,
267 NANOSECONDS.toDays(t*1000000000L*60*60*24));
268 }
269 }
270
271 /**
272 * convert saturates positive too-large values to Long.MAX_VALUE
273 * and negative to LONG.MIN_VALUE
274 */
275 public void testConvertSaturate() {
276 assertEquals(Long.MAX_VALUE,
277 NANOSECONDS.convert(Long.MAX_VALUE / 2, SECONDS));
278 assertEquals(Long.MIN_VALUE,
279 NANOSECONDS.convert(-Long.MAX_VALUE / 4, SECONDS));
280 assertEquals(Long.MAX_VALUE,
281 NANOSECONDS.convert(Long.MAX_VALUE / 2, MINUTES));
282 assertEquals(Long.MIN_VALUE,
283 NANOSECONDS.convert(-Long.MAX_VALUE / 4, MINUTES));
284 assertEquals(Long.MAX_VALUE,
285 NANOSECONDS.convert(Long.MAX_VALUE / 2, HOURS));
286 assertEquals(Long.MIN_VALUE,
287 NANOSECONDS.convert(-Long.MAX_VALUE / 4, HOURS));
288 assertEquals(Long.MAX_VALUE,
289 NANOSECONDS.convert(Long.MAX_VALUE / 2, DAYS));
290 assertEquals(Long.MIN_VALUE,
291 NANOSECONDS.convert(-Long.MAX_VALUE / 4, DAYS));
292
293 for (TimeUnit x : TimeUnit.values())
294 for (TimeUnit y : TimeUnit.values()) {
295 long ratio = x.toNanos(1) / y.toNanos(1);
296 if (ratio >= 1) {
297 assertEquals(ratio, y.convert(1, x));
298 assertEquals(1, x.convert(ratio, y));
299 long max = Long.MAX_VALUE/ratio;
300 assertEquals(max * ratio, y.convert(max, x));
301 assertEquals(-max * ratio, y.convert(-max, x));
302 assertEquals(max, x.convert(max * ratio, y));
303 assertEquals(-max, x.convert(-max * ratio, y));
304 if (max < Long.MAX_VALUE) {
305 assertEquals(Long.MAX_VALUE, y.convert(max + 1, x));
306 assertEquals(Long.MIN_VALUE, y.convert(-max - 1, x));
307 assertEquals(Long.MIN_VALUE, y.convert(Long.MIN_VALUE + 1, x));
308 }
309 assertEquals(Long.MAX_VALUE, y.convert(Long.MAX_VALUE, x));
310 assertEquals(Long.MIN_VALUE, y.convert(Long.MIN_VALUE, x));
311 }
312 }
313 }
314
315 /**
316 * toNanos saturates positive too-large values to Long.MAX_VALUE
317 * and negative to LONG.MIN_VALUE
318 */
319 public void testToNanosSaturate() {
320 assertEquals(Long.MAX_VALUE,
321 MILLISECONDS.toNanos(Long.MAX_VALUE / 2));
322 assertEquals(Long.MIN_VALUE,
323 MILLISECONDS.toNanos(-Long.MAX_VALUE / 3));
324
325 for (TimeUnit x : TimeUnit.values()) {
326 long ratio = x.toNanos(1) / NANOSECONDS.toNanos(1);
327 if (ratio >= 1) {
328 long max = Long.MAX_VALUE/ratio;
329 for (long z : new long[] {0, 1, -1, max, -max})
330 assertEquals(z * ratio, x.toNanos(z));
331 if (max < Long.MAX_VALUE) {
332 assertEquals(Long.MAX_VALUE, x.toNanos(max + 1));
333 assertEquals(Long.MIN_VALUE, x.toNanos(-max - 1));
334 assertEquals(Long.MIN_VALUE, x.toNanos(Long.MIN_VALUE + 1));
335 }
336 assertEquals(Long.MAX_VALUE, x.toNanos(Long.MAX_VALUE));
337 assertEquals(Long.MIN_VALUE, x.toNanos(Long.MIN_VALUE));
338 if (max < Integer.MAX_VALUE) {
339 assertEquals(Long.MAX_VALUE, x.toNanos(Integer.MAX_VALUE));
340 assertEquals(Long.MIN_VALUE, x.toNanos(Integer.MIN_VALUE));
341 }
342 }
343 }
344 }
345
346 /**
347 * toMicros saturates positive too-large values to Long.MAX_VALUE
348 * and negative to LONG.MIN_VALUE
349 */
350 public void testToMicrosSaturate() {
351 for (TimeUnit x : TimeUnit.values()) {
352 long ratio = x.toNanos(1) / MICROSECONDS.toNanos(1);
353 if (ratio >= 1) {
354 long max = Long.MAX_VALUE/ratio;
355 for (long z : new long[] {0, 1, -1, max, -max})
356 assertEquals(z * ratio, x.toMicros(z));
357 if (max < Long.MAX_VALUE) {
358 assertEquals(Long.MAX_VALUE, x.toMicros(max + 1));
359 assertEquals(Long.MIN_VALUE, x.toMicros(-max - 1));
360 assertEquals(Long.MIN_VALUE, x.toMicros(Long.MIN_VALUE + 1));
361 }
362 assertEquals(Long.MAX_VALUE, x.toMicros(Long.MAX_VALUE));
363 assertEquals(Long.MIN_VALUE, x.toMicros(Long.MIN_VALUE));
364 if (max < Integer.MAX_VALUE) {
365 assertEquals(Long.MAX_VALUE, x.toMicros(Integer.MAX_VALUE));
366 assertEquals(Long.MIN_VALUE, x.toMicros(Integer.MIN_VALUE));
367 }
368 }
369 }
370 }
371
372 /**
373 * toMillis saturates positive too-large values to Long.MAX_VALUE
374 * and negative to LONG.MIN_VALUE
375 */
376 public void testToMillisSaturate() {
377 for (TimeUnit x : TimeUnit.values()) {
378 long ratio = x.toNanos(1) / MILLISECONDS.toNanos(1);
379 if (ratio >= 1) {
380 long max = Long.MAX_VALUE/ratio;
381 for (long z : new long[] {0, 1, -1, max, -max})
382 assertEquals(z * ratio, x.toMillis(z));
383 if (max < Long.MAX_VALUE) {
384 assertEquals(Long.MAX_VALUE, x.toMillis(max + 1));
385 assertEquals(Long.MIN_VALUE, x.toMillis(-max - 1));
386 assertEquals(Long.MIN_VALUE, x.toMillis(Long.MIN_VALUE + 1));
387 }
388 assertEquals(Long.MAX_VALUE, x.toMillis(Long.MAX_VALUE));
389 assertEquals(Long.MIN_VALUE, x.toMillis(Long.MIN_VALUE));
390 if (max < Integer.MAX_VALUE) {
391 assertEquals(Long.MAX_VALUE, x.toMillis(Integer.MAX_VALUE));
392 assertEquals(Long.MIN_VALUE, x.toMillis(Integer.MIN_VALUE));
393 }
394 }
395 }
396 }
397
398 /**
399 * toSeconds saturates positive too-large values to Long.MAX_VALUE
400 * and negative to LONG.MIN_VALUE
401 */
402 public void testToSecondsSaturate() {
403 for (TimeUnit x : TimeUnit.values()) {
404 long ratio = x.toNanos(1) / SECONDS.toNanos(1);
405 if (ratio >= 1) {
406 long max = Long.MAX_VALUE/ratio;
407 for (long z : new long[] {0, 1, -1, max, -max})
408 assertEquals(z * ratio, x.toSeconds(z));
409 if (max < Long.MAX_VALUE) {
410 assertEquals(Long.MAX_VALUE, x.toSeconds(max + 1));
411 assertEquals(Long.MIN_VALUE, x.toSeconds(-max - 1));
412 assertEquals(Long.MIN_VALUE, x.toSeconds(Long.MIN_VALUE + 1));
413 }
414 assertEquals(Long.MAX_VALUE, x.toSeconds(Long.MAX_VALUE));
415 assertEquals(Long.MIN_VALUE, x.toSeconds(Long.MIN_VALUE));
416 if (max < Integer.MAX_VALUE) {
417 assertEquals(Long.MAX_VALUE, x.toSeconds(Integer.MAX_VALUE));
418 assertEquals(Long.MIN_VALUE, x.toSeconds(Integer.MIN_VALUE));
419 }
420 }
421 }
422 }
423
424 /**
425 * toMinutes saturates positive too-large values to Long.MAX_VALUE
426 * and negative to LONG.MIN_VALUE
427 */
428 public void testToMinutesSaturate() {
429 for (TimeUnit x : TimeUnit.values()) {
430 long ratio = x.toNanos(1) / MINUTES.toNanos(1);
431 if (ratio > 1) {
432 long max = Long.MAX_VALUE/ratio;
433 for (long z : new long[] {0, 1, -1, max, -max})
434 assertEquals(z * ratio, x.toMinutes(z));
435 assertEquals(Long.MAX_VALUE, x.toMinutes(max + 1));
436 assertEquals(Long.MIN_VALUE, x.toMinutes(-max - 1));
437 assertEquals(Long.MAX_VALUE, x.toMinutes(Long.MAX_VALUE));
438 assertEquals(Long.MIN_VALUE, x.toMinutes(Long.MIN_VALUE));
439 assertEquals(Long.MIN_VALUE, x.toMinutes(Long.MIN_VALUE + 1));
440 }
441 }
442 }
443
444 /**
445 * toHours saturates positive too-large values to Long.MAX_VALUE
446 * and negative to LONG.MIN_VALUE
447 */
448 public void testToHoursSaturate() {
449 for (TimeUnit x : TimeUnit.values()) {
450 long ratio = x.toNanos(1) / HOURS.toNanos(1);
451 if (ratio >= 1) {
452 long max = Long.MAX_VALUE/ratio;
453 for (long z : new long[] {0, 1, -1, max, -max})
454 assertEquals(z * ratio, x.toHours(z));
455 if (max < Long.MAX_VALUE) {
456 assertEquals(Long.MAX_VALUE, x.toHours(max + 1));
457 assertEquals(Long.MIN_VALUE, x.toHours(-max - 1));
458 assertEquals(Long.MIN_VALUE, x.toHours(Long.MIN_VALUE + 1));
459 }
460 assertEquals(Long.MAX_VALUE, x.toHours(Long.MAX_VALUE));
461 assertEquals(Long.MIN_VALUE, x.toHours(Long.MIN_VALUE));
462 }
463 }
464 }
465
466 /**
467 * toString returns name of unit
468 */
469 public void testToString() {
470 assertEquals("SECONDS", SECONDS.toString());
471 }
472
473 /**
474 * name returns name of unit
475 */
476 public void testName() {
477 assertEquals("SECONDS", SECONDS.name());
478 }
479
480 /**
481 * Timed wait without holding lock throws
482 * IllegalMonitorStateException
483 */
484 public void testTimedWait_IllegalMonitorException() {
485 Thread t = newStartedThread(new CheckedRunnable() {
486 public void realRun() throws InterruptedException {
487 Object o = new Object();
488 TimeUnit tu = MILLISECONDS;
489
490 try {
491 tu.timedWait(o, LONG_DELAY_MS);
492 threadShouldThrow();
493 } catch (IllegalMonitorStateException success) {}
494 }});
495
496 awaitTermination(t);
497 }
498
499 /**
500 * timedWait throws InterruptedException when interrupted
501 */
502 public void testTimedWait_Interruptible() {
503 final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
504 Thread t = newStartedThread(new CheckedRunnable() {
505 public void realRun() throws InterruptedException {
506 Object o = new Object();
507 TimeUnit tu = MILLISECONDS;
508
509 Thread.currentThread().interrupt();
510 try {
511 synchronized (o) {
512 tu.timedWait(o, LONG_DELAY_MS);
513 }
514 shouldThrow();
515 } catch (InterruptedException success) {}
516 assertFalse(Thread.interrupted());
517
518 pleaseInterrupt.countDown();
519 try {
520 synchronized (o) {
521 tu.timedWait(o, LONG_DELAY_MS);
522 }
523 shouldThrow();
524 } catch (InterruptedException success) {}
525 assertFalse(Thread.interrupted());
526 }});
527
528 await(pleaseInterrupt);
529 assertThreadBlocks(t, Thread.State.TIMED_WAITING);
530 t.interrupt();
531 awaitTermination(t);
532 }
533
534 /**
535 * timedJoin throws InterruptedException when interrupted
536 */
537 public void testTimedJoin_Interruptible() {
538 final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
539 final Thread s = newStartedThread(new CheckedInterruptedRunnable() {
540 public void realRun() throws InterruptedException {
541 Thread.sleep(LONG_DELAY_MS);
542 }});
543 final Thread t = newStartedThread(new CheckedRunnable() {
544 public void realRun() throws InterruptedException {
545 TimeUnit tu = MILLISECONDS;
546 Thread.currentThread().interrupt();
547 try {
548 tu.timedJoin(s, LONG_DELAY_MS);
549 shouldThrow();
550 } catch (InterruptedException success) {}
551 assertFalse(Thread.interrupted());
552
553 pleaseInterrupt.countDown();
554 try {
555 tu.timedJoin(s, LONG_DELAY_MS);
556 shouldThrow();
557 } catch (InterruptedException success) {}
558 assertFalse(Thread.interrupted());
559 }});
560
561 await(pleaseInterrupt);
562 assertThreadBlocks(t, Thread.State.TIMED_WAITING);
563 t.interrupt();
564 awaitTermination(t);
565 s.interrupt();
566 awaitTermination(s);
567 }
568
569 /**
570 * timedSleep throws InterruptedException when interrupted
571 */
572 public void testTimedSleep_Interruptible() {
573 final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
574 Thread t = newStartedThread(new CheckedRunnable() {
575 public void realRun() throws InterruptedException {
576 TimeUnit tu = MILLISECONDS;
577 Thread.currentThread().interrupt();
578 try {
579 tu.sleep(LONG_DELAY_MS);
580 shouldThrow();
581 } catch (InterruptedException success) {}
582 assertFalse(Thread.interrupted());
583
584 pleaseInterrupt.countDown();
585 try {
586 tu.sleep(LONG_DELAY_MS);
587 shouldThrow();
588 } catch (InterruptedException success) {}
589 assertFalse(Thread.interrupted());
590 }});
591
592 await(pleaseInterrupt);
593 assertThreadBlocks(t, Thread.State.TIMED_WAITING);
594 t.interrupt();
595 awaitTermination(t);
596 }
597
598 /**
599 * a deserialized serialized unit is the same instance
600 */
601 public void testSerialization() throws Exception {
602 for (TimeUnit x : TimeUnit.values())
603 assertSame(x, serialClone(x));
604 }
605
606 }

dl@cs.oswego.edu
ViewVC Help
Powered by ViewVC 1.1.27