jdk/test/javax/management/ObjectName/CompressedStorageTest.java
author rprotacio
Wed, 02 Mar 2016 15:10:38 -0500
changeset 36396 26a241a959de
parent 32415 24c214d2ccba
child 42338 a60f280f803c
permissions -rw-r--r--
8145098: JNI GetVersion should return JNI_VERSION_9 Summary: Updated JNI_VERSION for current version to be JNI_VERSION_9 Reviewed-by: hseigel, gtriantafill, dholmes, alanb

/*
 * Copyright (c) 2015, 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 8041565
 * @summary Tests the limits imposed on the domain name part of an
 *          ObjectName instance
 * @author Jaroslav Bachorik
 * @modules java.management
 * @run main CompressedStorageTest
 */

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.function.Consumer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

public class CompressedStorageTest {
    private static Method setDomainLengthM;
    private static Field compressedStorageFld;

    private static int DOMAIN_PATTERN;
    private static int PROPLIST_PATTERN;
    private static int PROPVAL_PATTERN;

    private static Method setDomainPattern;
    private static Method setPropertyListPattern;
    private static Method setPropertyValuePattern;


    static {
        try {
            Class<?> clz = ObjectName.class;
            setDomainLengthM = clz.getDeclaredMethod("setDomainLength", int.class);
            setDomainLengthM.setAccessible(true);

            compressedStorageFld = clz.getDeclaredField("_compressed_storage");
            compressedStorageFld.setAccessible(true);

            setDomainPattern = clz.getDeclaredMethod("setDomainPattern", boolean.class);
            setDomainPattern.setAccessible(true);
            setPropertyListPattern = clz.getDeclaredMethod("setPropertyListPattern", boolean.class);
            setPropertyListPattern.setAccessible(true);
            setPropertyValuePattern = clz.getDeclaredMethod("setPropertyValuePattern", boolean.class);
            setPropertyValuePattern.setAccessible(true);

            DOMAIN_PATTERN = getStaticIntFld("DOMAIN_PATTERN");
            PROPLIST_PATTERN = getStaticIntFld("PROPLIST_PATTERN");
            PROPVAL_PATTERN = getStaticIntFld("PROPVAL_PATTERN");

        } catch (Exception e) {
            throw new Error(e);
        }
    }

    public static void main(String[] args) throws Exception {
        testZeroLength();
        testNegativeLength();
        testMaxLength();

        testSetDomainPattern();
        testSetPropertyListPattern();
        testSetPropertyValuePattern();
    }

    private static ObjectName getObjectName()
    throws MalformedObjectNameException {
        return new ObjectName("domain", "key", "value");
    }

    /**
     * Test for accepting 0 being passed as argument to
     * {@linkplain ObjectName#setDomainLength(int)}.
     *
     */
    private static void testZeroLength() throws Exception {
        setDomainNameLength(0);
    }

    /**
     * Test for rejecting negative value being passed as argument to
     * {@linkplain ObjectName#setDomainLength(int)}.
     */
    private static void testNegativeLength() throws Exception {
        try {
            setDomainNameLength(-1);
        } catch (MalformedObjectNameException e) {
            return;
        }
        fail("Allowing negative domain name length");
    }

    /**
     * Test for rejecting value exceeding the maximum allowed length
     * being passed as argument to {@linkplain ObjectName#setDomainLength(int)}.
     */
    private static void testMaxLength() throws Exception {
        try {
            setDomainNameLength(Integer.MAX_VALUE / 4 + 1);
        } catch (MalformedObjectNameException e) {
            return;
        }
        fail("Maximum domain name length is not respected");
    }

    /**
     * Tests that calling {@linkplain ObjectName#setDomainPattern(boolean)}
     * results in setting correct bits in {@linkplain ObjectName#_compressed_storage}.
     */
    private static void testSetDomainPattern() throws Exception {
        ObjectName on = getObjectName();

        checkMask(DOMAIN_PATTERN, setDomainPattern, on);
    }

    /**
     * Tests that calling {@linkplain ObjectName#setPropertyListPattern(boolean)}
     * results in setting correct bits in {@linkplain ObjectName#_compressed_storage}.
     */
    private static void testSetPropertyListPattern() throws Exception {
        ObjectName on = getObjectName();

        checkMask(PROPLIST_PATTERN, setPropertyListPattern, on);
    }

    /**
     * Tests that calling {@linkplain ObjectName#setPropertyValuePattern(boolean)}
     * results in setting correct bits in {@linkplain ObjectName#_compressed_storage}.
     */
    private static void testSetPropertyValuePattern() throws Exception {
        ObjectName on = getObjectName();

        checkMask(PROPVAL_PATTERN, setPropertyValuePattern, on);
    }

    /**
     * Helper method to call {@linkplain ObjectName#setDomainLength(int)}
     * method via reflection.
     * @param len The domain name length
     * @throws MalformedObjectNameException Propagated from
     *           {@linkplain ObjectName#setDomainLength(int)} invocation.
     */
    private static void setDomainNameLength(int len)
    throws MalformedObjectNameException {
        try {
            setDomainLengthM.invoke(getObjectName(), len);
        } catch (InvocationTargetException e) {
            Throwable cause = e.getCause();
            if (cause instanceof MalformedObjectNameException) {
                throw (MalformedObjectNameException)cause;
            }
            throw new Error(cause);
        } catch (IllegalAccessException | IllegalArgumentException e) {
            throw new Error(e);
        }
    }

    /**
     * Helper method to assert that a particular boolean setter affects only
     * a particular bit in the {@linkplain ObjectName#_compressed_storage} field.
     * @param mask bitmask for storing the boolean value
     * @param setter setter method reference
     * @param on {@linkplain ObjectName} instance
     */
    private static void checkMask(int mask, Method setter, ObjectName on)
    throws Exception {
        int valBefore = compressedStorageFld.getInt(on);
        setter.invoke(on, true);
        int valAfter = compressedStorageFld.getInt(on);

        checkMask(mask, valAfter ^ valBefore);

        valBefore = valAfter;
        setter.invoke(on, false);
        valAfter = compressedStorageFld.getInt(on);

        checkMask(mask, valAfter ^ valBefore);
    }

    /**
     * Compare the changed bits with the given mask.
     * @param mask bitmask
     * @param val the changed bits; may be 0 if there was no change
     */
    private static void checkMask(int mask, int val) {
        if (val != 0 && val != mask) {
            fail("Invalid mask: expecting '" +
                    Integer.toBinaryString(mask) + "' , received '" +
                    Integer.toBinaryString(val) + "'");
        }
    }

    /**
     * Helper method to obtain the value of a static field via reflection.
     * @param name static field name
     * @return static field value
     */
    private static int getStaticIntFld(String name) throws Exception {
        Field fld = ObjectName.class.getDeclaredField(name);
        fld.setAccessible(true);

        return fld.getInt(null);
    }

    private static void fail(String msg) {
        throw new Error(msg);
    }
}