/*
 * 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 6464365
 * @summary Test state transitions; check protected methods are called
 * @author Martin Buchholz
 */

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

public class Customized {
    static final AtomicLong doneCount = new AtomicLong(0);
    static final AtomicLong setCount = new AtomicLong(0);
    static final AtomicLong setExceptionCount = new AtomicLong(0);

    static void equal(long expected, AtomicLong actual) {
        equal(expected, actual.get());
    }

    static void equalCounts(long x, long y, long z) {
        equal(x, doneCount);
        equal(y, setCount);
        equal(z, setExceptionCount);
    }

    static class MyFutureTask<V> extends FutureTask<V> {
        MyFutureTask(Runnable r, V result) { super(r, result); }
        protected void done() {
            doneCount.getAndIncrement();
            super.done();
        }
        protected void set(V v) {
            setCount.getAndIncrement();
            super.set(v);
        }
        protected void setException(Throwable t) {
            setExceptionCount.getAndIncrement();
            super.setException(t);
        }
        public boolean runAndReset() {
            return super.runAndReset();
        }
    }

    static <V> void checkReady(final FutureTask<V> task) {
        check(! task.isDone());
        check(! task.isCancelled());
        THROWS(TimeoutException.class,
               new Fun(){void f() throws Throwable {
                       task.get(0L, TimeUnit.SECONDS); }});
    }

    static <V> void checkDone(final FutureTask<V> task) {
        try {
            check(task.isDone());
            check(! task.isCancelled());
            check(task.get() != null);
        } catch (Throwable t) { unexpected(t); }
    }

    static <V> void checkCancelled(final FutureTask<V> task) {
        check(task.isDone());
        check(task.isCancelled());
        THROWS(CancellationException.class,
           new Fun(){void f() throws Throwable {
               task.get(0L, TimeUnit.SECONDS); }},
           new Fun(){void f() throws Throwable {
               task.get(); }});
    }

    static <V> void checkThrew(final FutureTask<V> task) {
        check(task.isDone());
        check(! task.isCancelled());
        THROWS(ExecutionException.class,
           new Fun(){void f() throws Throwable {
               task.get(0L, TimeUnit.SECONDS); }},
           new Fun(){void f() throws Throwable {
               task.get(); }});
    }

    static <V> void cancel(FutureTask<V> task, boolean mayInterruptIfRunning) {
        task.cancel(mayInterruptIfRunning);
        checkCancelled(task);
    }

    static <V> void run(FutureTask<V> task) {
        boolean isCancelled = task.isCancelled();
        task.run();
        check(task.isDone());
        equal(isCancelled, task.isCancelled());
    }

    static void realMain(String[] args) throws Throwable {
        final Runnable nop = new Runnable() {
                public void run() {}};
        final Runnable bad = new Runnable() {
                public void run() { throw new Error(); }};

        try {
            final MyFutureTask<Long> task = new MyFutureTask<Long>(nop, 42L);
            checkReady(task);
            equalCounts(0,0,0);
            check(task.runAndReset());
            checkReady(task);
            equalCounts(0,0,0);
            run(task);
            checkDone(task);
            equalCounts(1,1,0);
            equal(42L, task.get());
            run(task);
            checkDone(task);
            equalCounts(1,1,0);
            equal(42L, task.get());
        } catch (Throwable t) { unexpected(t); }

        try {
            final MyFutureTask<Long> task = new MyFutureTask<Long>(nop, 42L);
            cancel(task, false);
            equalCounts(2,1,0);
            cancel(task, false);
            equalCounts(2,1,0);
            run(task);
            equalCounts(2,1,0);
            check(! task.runAndReset());
        } catch (Throwable t) { unexpected(t); }

        try {
            final MyFutureTask<Long> task = new MyFutureTask<Long>(bad, 42L);
            checkReady(task);
            run(task);
            checkThrew(task);
            equalCounts(3,1,1);
            run(task);
            equalCounts(3,1,1);
        } catch (Throwable t) { unexpected(t); }

        try {
            final MyFutureTask<Long> task = new MyFutureTask<Long>(nop, 42L);
            checkReady(task);
            task.set(99L);
            checkDone(task);
            equalCounts(4,2,1);
            run(task);
            equalCounts(4,2,1);
            task.setException(new Throwable());
            checkDone(task);
            equalCounts(4,2,2);
        } catch (Throwable t) { unexpected(t); }

        try {
            final MyFutureTask<Long> task = new MyFutureTask<Long>(nop, 42L);
            checkReady(task);
            task.setException(new Throwable());
            checkThrew(task);
            equalCounts(5,2,3);
            run(task);
            equalCounts(5,2,3);
            task.set(99L);
            checkThrew(task);
            equalCounts(5,3,3);
        } catch (Throwable t) { unexpected(t); }

        System.out.printf("doneCount=%d%n", doneCount.get());
        System.out.printf("setCount=%d%n", setCount.get());
        System.out.printf("setExceptionCount=%d%n", setExceptionCount.get());
    }

    //--------------------- Infrastructure ---------------------------
    static volatile int passed = 0, failed = 0;
    static void pass() {passed++;}
    static void fail() {failed++; Thread.dumpStack();}
    static void fail(String msg) {System.out.println(msg); fail();}
    static void unexpected(Throwable t) {failed++; t.printStackTrace();}
    static void check(boolean cond) {if (cond) pass(); else fail();}
    static 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 {
        try {realMain(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");}
    private static abstract class Fun {abstract void f() throws Throwable;}
    static void THROWS(Class<? extends Throwable> k, Fun... fs) {
        for (Fun f : fs)
            try { f.f(); fail("Expected " + k.getName() + " not thrown"); }
            catch (Throwable t) {
                if (k.isAssignableFrom(t.getClass())) pass();
                else unexpected(t);}}
}
