/*
 * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/*
 * @test
 * @bug 6571655 6571881 6574585 6571297
 * @summary Test various args to task scheduling methods
 */

import java.util.*;
import java.util.concurrent.*;

public class Args {
    void schedule(final Timer t, final TimerTask task, final Date d) {
        t.schedule(task, d);
        THROWS(IllegalStateException.class,
               new F(){void f(){ t.schedule(task, d); }});
    }

    void schedule(final Timer t, final TimerTask task, final Date d, final long period) {
        t.schedule(task, d, period);
        THROWS(IllegalStateException.class,
               new F(){void f(){ t.schedule(task, d, period); }});
    }

    void scheduleAtFixedRate(final Timer t, final TimerTask task, final Date d, final long period) {
        t.scheduleAtFixedRate(task, d, period);
        THROWS(IllegalStateException.class,
               new F(){void f(){ t.scheduleAtFixedRate(task, d, period); }});
    }

    TimerTask counter(final CountDownLatch latch) {
        return new TimerTask() { public void run() {
            check(latch.getCount() > 0);
            latch.countDown();
        }};
    }

    void test(String[] args) throws Throwable {
        final Timer t = new Timer();
        final TimerTask x = new TimerTask() { public void run() {}};
        THROWS(IllegalArgumentException.class,
               new F(){void f(){ t.schedule(x, -42); }},
               new F(){void f(){ t.schedule(x, new Date(-42)); }},

               new F(){void f(){ t.schedule(x, Long.MAX_VALUE); }},
               new F(){void f(){ t.schedule(x, -42, 42); }},
               new F(){void f(){ t.schedule(x, new Date(-42), 42); }},
               new F(){void f(){ t.schedule(x, Long.MAX_VALUE, 42); }},
               new F(){void f(){ t.schedule(x, 42, 0); }},
               new F(){void f(){ t.schedule(x, new Date(42), 0); }},
               new F(){void f(){ t.schedule(x, 42, -42); }},
               new F(){void f(){ t.schedule(x, new Date(42), -42); }},

               new F(){void f(){ t.scheduleAtFixedRate(x, -42, 42); }},
               new F(){void f(){ t.scheduleAtFixedRate(x, new Date(-42), 42); }},
               new F(){void f(){ t.scheduleAtFixedRate(x, Long.MAX_VALUE, 42); }},
               new F(){void f(){ t.scheduleAtFixedRate(x, 42, 0); }},
               new F(){void f(){ t.scheduleAtFixedRate(x, new Date(42), 0); }},
               new F(){void f(){ t.scheduleAtFixedRate(x, 42, -42); }},
               new F(){void f(){ t.scheduleAtFixedRate(x, new Date(42), -42); }}
               );

        THROWS(NullPointerException.class,
               new F(){void f(){ t.schedule(null, 42); }},
               new F(){void f(){ t.schedule(x, (Date)null); }},

               new F(){void f(){ t.schedule(null, 42, 42); }},
               new F(){void f(){ t.schedule(x, (Date)null, 42); }},

               new F(){void f(){ t.scheduleAtFixedRate(null, 42, 42); }},
               new F(){void f(){ t.scheduleAtFixedRate(x, (Date)null, 42); }}
               );

        final long start = System.currentTimeMillis();
        final Date past = new Date(start - 10500);
        final CountDownLatch y1 = new CountDownLatch(1);
        final CountDownLatch y2 = new CountDownLatch(1);
        final CountDownLatch y3 = new CountDownLatch(11);
        schedule(           t, counter(y1), past);
        schedule(           t, counter(y2), past, 1000);
        scheduleAtFixedRate(t, counter(y3), past, 1000);
        y3.await();
        y1.await();
        y2.await();
        System.out.printf("elapsed=%d%n", System.currentTimeMillis() - start);
        check(System.currentTimeMillis() - start < 500);

        t.cancel();

        THROWS(IllegalStateException.class,
               new F(){void f(){ t.schedule(x, 42); }},
               new F(){void f(){ t.schedule(x, past); }},
               new F(){void f(){ t.schedule(x, 42, 42); }},
               new F(){void f(){ t.schedule(x, past, 42); }},
               new F(){void f(){ t.scheduleAtFixedRate(x, 42, 42); }},
               new F(){void f(){ t.scheduleAtFixedRate(x, past, 42); }});

    }

    //--------------------- Infrastructure ---------------------------
    volatile int passed = 0, failed = 0;
    void pass() {passed++;}
    void fail() {failed++; Thread.dumpStack();}
    void fail(String msg) {System.err.println(msg); fail();}
    void unexpected(Throwable t) {failed++; t.printStackTrace();}
    void check(boolean cond) {if (cond) pass(); else fail();}
    void equal(Object x, Object y) {
        if (x == null ? y == null : x.equals(y)) pass();
        else fail(x + " not equal to " + y);}
    public static void main(String[] args) throws Throwable {
        new Args().instanceMain(args);}
    void instanceMain(String[] args) throws Throwable {
        try {test(args);} catch (Throwable t) {unexpected(t);}
        System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
        if (failed > 0) throw new AssertionError("Some tests failed");}
    abstract class F {abstract void f() throws Throwable;}
    void THROWS(Class<? extends Throwable> k, F... fs) {
        for (F f : fs)
            try {f.f(); fail("Expected " + k.getName() + " not thrown");}
            catch (Throwable t) {
                if (k.isAssignableFrom(t.getClass())) pass();
                else unexpected(t);}}
}
