/*
 * Copyright (c) 2012, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @bug 7103570
 * @author David Holmes
 * @run main/othervm AtomicUpdaters
 * @run main/othervm AtomicUpdaters UseSM
 * @summary Checks the (in)ability to create field updaters for differently
 *          accessible fields in different locations with/without a security
 *          manager
 */
import java.util.concurrent.atomic.*;
import java.lang.reflect.*;
import java.security.AccessControlException;

public class  AtomicUpdaters {
    enum TYPE { INT, LONG, REF }

    static class Config {
        final Class<?> clazz;
        final String field;
        final String access;
        final boolean reflectOk;
        final boolean updaterOk;
        final String desc;
        final TYPE type;

        Config(Class<?> clazz, String field, String access,
               boolean reflectOk, boolean updaterOk, String desc, TYPE type) {
            this.clazz = clazz;
            this.field = field;
            this.access = access;
            this.reflectOk = reflectOk;
            this.updaterOk = updaterOk;
            this.desc = desc;
            this.type =type;
        }

        public String toString() {
            return desc + ": " + access + " " + clazz.getName() + "." + field;
        }
    }

    static Config[] tests;

    static void initTests(boolean hasSM) {
        tests = new Config[] {
            new Config(AtomicUpdaters.class, "pub_int", "public", true, true, "public int field of current class", TYPE.INT),
            new Config(AtomicUpdaters.class, "priv_int", "private", true, true, "private int field of current class", TYPE.INT),
            new Config(AtomicUpdaters.class, "pub_long", "public", true, true, "public long field of current class", TYPE.LONG),
            new Config(AtomicUpdaters.class, "priv_long", "private", true, true, "private long field of current class", TYPE.LONG),
            new Config(AtomicUpdaters.class, "pub_ref", "public", true, true, "public ref field of current class", TYPE.REF),
            new Config(AtomicUpdaters.class, "priv_ref", "private", true, true, "private ref field of current class", TYPE.REF),

            // Would like to test a public volatile in a class in another
            // package - but of course there aren't any
            new Config(java.util.concurrent.atomic.AtomicInteger.class, "value", "private", hasSM ? false : true, false, "private int field of class in different package", TYPE.INT),
            new Config(java.util.concurrent.atomic.AtomicLong.class, "value", "private", hasSM ? false : true, false, "private long field of class in different package", TYPE.LONG),
            new Config(java.util.concurrent.atomic.AtomicReference.class, "value", "private", hasSM ? false : true, false, "private reference field of class in different package", TYPE.REF),
        };
    }

    public volatile int pub_int;
    private volatile int priv_int;
    public volatile long pub_long;
    private volatile long priv_long;
    public volatile Object pub_ref;
    private volatile Object priv_ref;


    // This should be set dynamically at runtime using a System property, but
    // ironically we get a SecurityException if we try to do that with a
    // SecurityManager installed
    static boolean verbose;

    public static void main(String[] args) throws Throwable {
        boolean hasSM = false;
        for (String arg : args) {
            if ("-v".equals(arg)) {
                verbose = true;
            }
            else if ("UseSM".equals(arg)) {
                SecurityManager m = System.getSecurityManager();
                if (m != null)
                    throw new RuntimeException("No security manager should initially be installed");
                System.setSecurityManager(new java.lang.SecurityManager());
                hasSM = true;
            }
            else {
                throw new IllegalArgumentException("Unexpected option: " + arg);
            }
        }
        initTests(hasSM);

        int failures = 0;

        System.out.printf("Testing with%s a SecurityManager present\n", hasSM ? "" : "out");
        for (Config c : tests) {
            System.out.println("Testing: " + c);
            Error reflectionFailure = null;
            Error updaterFailure = null;
            Class<?> clazz = c.clazz;
            // See if we can reflectively access the field
            System.out.println(" - testing getDeclaredField");
            try {
                Field f = clazz.getDeclaredField(c.field);
                if (!c.reflectOk)
                    reflectionFailure = new Error("Unexpected reflective access: " + c);
            }
            catch (AccessControlException e) {
                if (c.reflectOk)
                    reflectionFailure = new Error("Unexpected reflective access failure: " + c, e);
                else if (verbose) {
                    System.out.println("Got expected reflection exception: " + e);
                    e.printStackTrace(System.out);
                }
            }

            if (reflectionFailure != null) {
                reflectionFailure.printStackTrace(System.out);
            }

            // see if we can create an atomic updater for the field
            Object u = null;
            try {
                switch (c.type) {
                case INT:
                    System.out.println(" - testing AtomicIntegerFieldUpdater");
                    u = AtomicIntegerFieldUpdater.newUpdater(clazz, c.field);
                    break;
                case LONG:
                    System.out.println(" - testing AtomicLongFieldUpdater");
                    u = AtomicLongFieldUpdater.newUpdater(clazz, c.field);
                    break;
                case REF:
                    System.out.println(" - testing AtomicReferenceFieldUpdater");
                    u = AtomicReferenceFieldUpdater.newUpdater(clazz, Object.class, c.field);
                    break;
                }

                if (!c.updaterOk)
                    updaterFailure =  new Error("Unexpected updater access: " + c);
            }
            catch (Exception e) {
                if (c.updaterOk)
                    updaterFailure = new Error("Unexpected updater access failure: " + c, e);
                else if (verbose) {
                    System.out.println("Got expected updater exception: " + e);
                    e.printStackTrace(System.out);
                }
            }

            if (updaterFailure != null) {
                updaterFailure.printStackTrace(System.out);
            }

            if (updaterFailure != null || reflectionFailure != null) {
                failures++;

            }
        }

        if (failures > 0) {
            throw new Error("Some tests failed - see previous stacktraces");
        }
    }
}
