jdk/test/javax/management/namespace/SerialParamProcessorTest.java
author dfuchs
Wed, 10 Sep 2008 16:27:13 +0200
changeset 1227 4546977d0d66
parent 1156 bbc2d15aaf7a
permissions -rw-r--r--
6746754: jmx namespace: test for leading separator missing 6669137: RFE: InstanceNotFoundException should have a constructor that takes an ObjectName 6746796: jmx namespaces: Several tests are missing an @bug or @run keyword Summary: Note on 6669137: first implementation of 6669137 was actually pushed with 5072476 - here we only have a small update and a test case. Also re-fixes 6737133: Compilation failure of test/javax/management/eventService/LeaseManagerDeadlockTest.java which had failed. Reviewed-by: emcmanus, yjoan

/*
 * Copyright 2008 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 SerialParamProcessorTest.java 1.8
 * @summary General SerialParamProcessorTest test.
 * @author Daniel Fuchs
 * @bug 5072476
 * @run clean SerialParamProcessorTest Wombat WombatMBean
 * @compile -XDignore.symbol.file=true  SerialParamProcessorTest.java
 * @run build SerialParamProcessorTest Wombat WombatMBean
 * @run main SerialParamProcessorTest
 */

import com.sun.jmx.namespace.serial.RewritingProcessor;
import java.beans.ConstructorProperties;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.management.AttributeChangeNotification;
import javax.management.AttributeList;
import javax.management.JMException;
import javax.management.Notification;
import javax.management.ObjectName;
import javax.management.StandardMBean;

/**
 * Class SerialParamProcessorTest
 *
 * @author Sun Microsystems, Inc.
 */
public class SerialParamProcessorTest {

    /**
     * Creates a new instance of SerialParamProcessorTest
     */
    public SerialParamProcessorTest() {
    }

    public static class MyCompositeData implements Serializable {
        private static final long serialVersionUID = 3186492415099133506L;
        public MyCompositeData(ObjectName foobar,ObjectName absolute,
                long count, String name) {
            this(foobar,absolute,count,name,new ObjectName[]{foobar,absolute});
        }
        @ConstructorProperties(value={"fooBar","absolute","count","name",
                                        "allNames"})
        public MyCompositeData(ObjectName foobar,ObjectName absolute,
                long count, String name, ObjectName[] allnames) {
            this.foobar = foobar;
            this.absolute = absolute;
            this.count = count;
            this.name = name;
            this.allnames = allnames;
        }
        ObjectName foobar,absolute,allnames[];
        long count;
        String name;
        public ObjectName getFooBar() {
            return foobar;
        }
        public ObjectName getAbsolute() {
            return absolute;
        }
        public ObjectName[] getAllNames() {
            return allnames;
        }
        public long getCount() {
            return count;
        }
        public String getName() {
            return name;
        }
        private Object[] toArray() {
            final Object[] props = {
                getName(),getFooBar(),getAbsolute(),getAllNames(),getCount()
            };
            return props;
        }
        @Override
        public boolean equals(Object o) {
            if (o instanceof MyCompositeData)
                return Arrays.deepEquals(toArray(),
                        ((MyCompositeData)o).toArray());
            return false;
        }
        @Override
        public int hashCode() {
            return Arrays.deepHashCode(toArray());
        }
    }

    public static interface MyMXBean {
        public Map<String,MyCompositeData> getAll();
        public MyCompositeData lookup(String name);
        public void put(String name, MyCompositeData data);
        public MyCompositeData remove(String name);
    }

    public static class My implements MyMXBean {
        Map<String,MyCompositeData> datas =
                new HashMap<String,MyCompositeData>();
        public Map<String,MyCompositeData> getAll() {
            return datas;
        }
        public MyCompositeData lookup(String name) {
            return datas.get(name);
        }
        public void put(String name, MyCompositeData data) {
            datas.put(name,data);
        }
        public MyCompositeData remove(String name) {
            return datas.remove(name);
        }
    }

    public static class BandicootClass implements Serializable {
        private static final long serialVersionUID = -5494055748633966355L;
        public final Object gloups;
        public BandicootClass(Object gloups) {
            this.gloups = gloups;
        }
        private Object[] toArray() {
            final Object[] one = {gloups};
            return one;
        }
        @Override
        public boolean equals(Object obj) {
            if (!(obj instanceof BandicootClass)) return false;
            final Object[] one = {gloups};
            return Arrays.deepEquals(toArray(),((BandicootClass)obj).toArray());
        }
        @Override
        public int hashCode() {
            if (gloups == null) return 0;
            return Arrays.deepHashCode(toArray());
        }
    }

    // Need this to override equals.
    public static class BandicootNotification extends Notification {
        private static final long serialVersionUID = 664758643764049001L;
        public BandicootNotification(String type, Object source, long seq) {
            super(type,source,seq,0L,"");
        }
        private Object[] toArray() {
            final Object[] vals = {getMessage(),getSequenceNumber(),
                getSource(),getTimeStamp(),getType(),getUserData()};
            return vals;
        }
        @Override
        public boolean equals(Object o) {
            if (!(o instanceof BandicootNotification)) return false;
            return Arrays.deepEquals(toArray(),
                    ((BandicootNotification)o).toArray());
        }
        @Override
        public int hashCode() {
            return Arrays.deepHashCode(toArray());
        }

    }

    // Need this to override equals.
    public static class BandicootAttributeChangeNotification
            extends AttributeChangeNotification {
        private static final long serialVersionUID = -1392435607144396125L;
        public BandicootAttributeChangeNotification(Object source,
                long seq, long time, String msg, String name, String type,
                Object oldv, Object newv) {
            super(source,seq,time,msg,name,type,oldv,newv);
        }
        private Object[] toArray() {
            final Object[] vals = {getMessage(),getSequenceNumber(),
                getSource(),getTimeStamp(),getType(),getUserData(),
                getAttributeName(), getAttributeType(),getNewValue(),
                getOldValue()};
            return vals;
        }
        @Override
        public boolean equals(Object o) {
            if (!(o instanceof BandicootAttributeChangeNotification))
                return false;
            return Arrays.deepEquals(toArray(),
                    ((BandicootAttributeChangeNotification)o).toArray());
        }
        @Override
        public int hashCode() {
            return Arrays.deepHashCode(toArray());
        }
        @Override
        public String toString() {
            final StringBuilder b = new StringBuilder();
            b.append(this.getClass().getName()).append(": ");
            b.append("[type=").append(getType()).append("]");
            b.append("[source=").append(getSource()).append("]");
            b.append("[message=").append(getMessage()).append("]");
            b.append("[sequence=").append(getSequenceNumber()).append("]");

            b.append("[attribute=").append(getAttributeName()).append("]");
            b.append("[class=").append(getAttributeType()).append("]");
            b.append("[oldvalue=").append(getOldValue()).append("]");
            b.append("[newvalue=").append(getNewValue()).append("]");

            b.append("[time=").append(getTimeStamp()).append("]");
            b.append("[data=").append(getUserData()).append("]");
            return b.toString();
        }
    }

    private static void addToList(Object[] foos, List<Object> foolist) {
        final ArrayList<Object> fal = new ArrayList<Object>(foos.length);
        for (Object f : foos) {
            if (f.getClass().isArray()) {
                foolist.add(new BandicootClass(f));
                fal.add(new BandicootClass(f));
            } else {
                foolist.add(f);
                fal.add(f);
            }
        }
        foolist.add(new BandicootClass(foos));
        foolist.add(fal);
    }

    public static void testSerial(String msg, Object foo, Object bar,
            RewritingProcessor procForFoo,
            RewritingProcessor procForBar, List<Object> foolist,
            List<Object> barlist, boolean recurse) {
        System.err.println(msg+" Testing serial - "+foo.getClass().getName());
        final Object bar1  = procForFoo.rewriteInput(foo);
        final Object foo1  = procForFoo.rewriteOutput(bar);
        final Object bar2  = procForFoo.rewriteInput(foo1);
        final Object foo2  = procForFoo.rewriteOutput(bar1);

        final Object bar3  = procForBar.rewriteOutput(foo);
        final Object foo3  = procForBar.rewriteInput(bar);
        final Object bar4  = procForBar.rewriteOutput(foo3);
        final Object foo4  = procForBar.rewriteInput(bar3);

        final Object bar5  = procForFoo.rewriteInput(foo3);
        final Object foo5  = procForFoo.rewriteOutput(bar3);

        final Object bar6  = procForBar.rewriteOutput(foo1);
        final Object foo6  = procForBar.rewriteInput(bar1);

        final Object[] foos = {foo, foo1, foo2, foo3, foo4, foo5, foo6};
        final Object[] bars = {bar, bar1, bar2, bar3, bar4, bar5, bar6};

        final Object[] foot = { foo };
        final Object[] bart = { bar };
        for (int j=1;j<foos.length;j++) {
            final Object[] foox = { foos[j] };
            final Object[] barx = { bars[j] };
            if (!Arrays.deepEquals(foot,foox)) {
                System.err.println(msg+" foo"+j+" "+foos[j]+" != "+foo);
                throw new RuntimeException(msg+" foo"+j+" != foo");
            }
            if (!Arrays.deepEquals(bart,barx)) {
                System.err.println(msg+" bar"+j+" "+bars[j]+" != "+bar);
                throw new RuntimeException(msg+" bar"+j+" != bar");
            }

        }
        if (recurse) {
            testSerial("Array: " + msg,foos,bars,procForFoo,
                    procForBar,foolist,barlist,false);
            addToList(foos,foolist);
            addToList(bars,barlist);
        }
    }
    public static void testSerial(Object[][] objects,
            RewritingProcessor procForFoo,
            RewritingProcessor procForBar) {
        int i=0;
        final List<Object> foolist  = new LinkedList<Object>();
        final List<Object> barlist = new LinkedList<Object>();
        for (Object[] row : objects) {
            i++;
            Object foo = row[0];
            Object bar = row[1];
            String msg1 = "[" +foo.getClass().getName() + "] step " +
                    i +": ";

            testSerial(msg1,foo,bar,procForFoo,procForBar,foolist,barlist,true);

            final BandicootClass kfoo = new BandicootClass(foo);
            final BandicootClass kbar = new BandicootClass(bar);

            String msg2 = "[" +kfoo.getClass().getName() + "] step " +
                    i +": ";
            testSerial(msg2,kfoo,kbar,procForFoo,procForBar,foolist,barlist,true);
        }
        String msg31 = "foo[] and bar[]: ";
        testSerial(msg31,foolist.toArray(),barlist.toArray(),
                   procForFoo,procForBar,foolist,barlist,false);

        String msg3 = "foolist and barlist: ";
        testSerial(msg3,new LinkedList<Object>(foolist),
                   new LinkedList<Object>(barlist),
                   procForFoo,procForBar,foolist,barlist,false);

        final BandicootClass kfoolist = new BandicootClass(foolist);
        final BandicootClass kbarlist = new BandicootClass(barlist);
        String msg4 = "kfoolist and kbarlist: ";
        testSerial(msg4,kfoolist,kbarlist,procForFoo,procForBar,foolist,barlist,false);
    }

    /**
     * The idea of this  method is to convert {@code foo} things into
     * {@code bar} things...
     * @param foo the string to replace.
     * @param bar the replacement for {@code foo}
     *        ({@code foo} becomes {@code bar}).
     * @param sfoo a string that may contain {@code foo}, that will be embedded
     *        in non-replaceable parts of the domain in order to attempt to
     *        trick the replacement logic.
     * @param sbar a string that may contain {@code bar}, that will be embedded
     *        in non-replaceable parts of the domain in order to attempt to
     *        trick the replacement logic.
     **/
    public static void doSerialTest(String foo, String bar, String sfoo,
                               String sbar) {
        try {
        final RewritingProcessor procForFoo = RewritingProcessor.
                newRewritingProcessor(foo,bar);
        final RewritingProcessor procForBar =RewritingProcessor.
                newRewritingProcessor(bar,foo);
        final String foop = (foo.isEmpty())?foo:foo+"//";
        final String pfoo = (foo.isEmpty())?foo:"//"+foo;
        final String barp = (bar.isEmpty())?bar:bar+"//";
        final String pbar = (bar.isEmpty())?bar:"//"+bar;
        final String sfoop = (sfoo.isEmpty())?sfoo:sfoo+"//";
        final String psfoo = (sfoo.isEmpty())?sfoo:"//"+sfoo;
        final String sbarp = (sbar.isEmpty())?sbar:sbar+"//";
        final String psbar = (sbar.isEmpty())?sbar:"//"+sbar;

        // A trick to avoid writing Open Data by hand...
        final My tricks = new My();

        // A treat to automagically convert trick things into Open Data.
        final StandardMBean treats =
                new StandardMBean(tricks,MyMXBean.class,true);

        // datas[i][0] is expected to be transformed in datas[i][1]
        //
        final MyCompositeData[][] datas = {
            { // this foo thing:
            new MyCompositeData(new ObjectName(foop+sbarp+"x:y=z"),
                    new ObjectName("//"+foop+sbarp+"x:y=z"),1,sfoop+sbarp+"foobar"),
              // should be transformed into this bar thing:
            new MyCompositeData(new ObjectName(barp+sbarp+"x:y=z"),
                    new ObjectName("//"+foop+sbarp+"x:y=z"),1,sfoop+sbarp+"foobar"),
            },
            { // this foo thing:
            new MyCompositeData(new ObjectName(foop+sfoop+"x:y=z"),
                    new ObjectName("//"+foop+sfoop+"x:y=z"),1,sfoop+sbarp+"barfoo"),
              // should be transformed into this bar thing:
            new MyCompositeData(new ObjectName(barp+sfoop+"x:y=z"),
                    new ObjectName("//"+foop+sfoop+"x:y=z"),1,sfoop+sbarp+"barfoo"),
            }
        };

        // objects[i][0] is expected to be transformed into objects[i][1]
        //
        final Object[][] objects = new Object[][] {
            {new Long(1), new Long(1)},
            {
                new ObjectName(foop+sbarp+"x:y=z"),
                        new ObjectName(barp+sbarp+"x:y=z")
            },
            {
                new ObjectName(foop+sfoop+"x:y=z"),
                        new ObjectName(barp+sfoop+"x:y=z")
            },
            {
                new ObjectName("//"+foop+sbarp+"x:y=z"),
                new ObjectName("//"+foop+sbarp+"x:y=z"),
            },
            {
                new ObjectName("//"+foop+sfoop+"x:y=z"),
                new ObjectName("//"+foop+sfoop+"x:y=z")
            },
            {
                foop+sbarp+"x:y=z",foop+sbarp+"x:y=z"
            },
            {
                foop+sfoop+"x:y=z",foop+sfoop+"x:y=z"
            },
            {
                barp+sbarp+"x:y=z",barp+sbarp+"x:y=z"
            },
            {
                barp+sfoop+"x:y=z",barp+sfoop+"x:y=z"
            },
            {
            new BandicootNotification("test",new ObjectName(foop+sfoop+"x:y=z"),1L),
            new BandicootNotification("test",new ObjectName(barp+sfoop+"x:y=z"),1L),
            },
            {
            new BandicootNotification("test",new ObjectName("//"+foop+sfoop+"x:y=z"),2L),
            new BandicootNotification("test",new ObjectName("//"+foop+sfoop+"x:y=z"),2L),
            },
            {
            new BandicootAttributeChangeNotification(
                    new ObjectName(foop+sfoop+"x:y=z"),1L,2L,"blah","attrname",
                    ObjectName.class.getName(),
                    new ObjectName(foop+sfoop+"x:y=old"),
                    new ObjectName(foop+sfoop+"x:y=new")),
            new BandicootAttributeChangeNotification(
                    new ObjectName(barp+sfoop+"x:y=z"),1L,2L,"blah","attrname",
                    ObjectName.class.getName(),
                    new ObjectName(barp+sfoop+"x:y=old"),
                    new ObjectName(barp+sfoop+"x:y=new")),
            },
            {
            new BandicootAttributeChangeNotification(
                    new ObjectName("//"+foop+sfoop+"x:y=z"),1L,2L,"blah","attrname",
                    ObjectName.class.getName(),
                    new ObjectName("//"+foop+sfoop+"x:y=old"),
                    new ObjectName(foop+sfoop+"x:y=new")),
            new BandicootAttributeChangeNotification(
                    new ObjectName("//"+foop+sfoop+"x:y=z"),1L,2L,"blah","attrname",
                    ObjectName.class.getName(),
                    new ObjectName("//"+foop+sfoop+"x:y=old"),
                    new ObjectName(barp+sfoop+"x:y=new")),
            }
        };

        // List that will merge datas & objects & datas converted to open
        // types...
        //
        final List<Object[]> list = new ArrayList<Object[]>();

        // Add all objects...
        //
        list.addAll(Arrays.asList(objects));

        // Build Map<String,MyCompositeData> with datas[i][0] (cfoo)
        //
        for (int i=0;i<datas.length;i++) {
            tricks.put(sfoop+sbarp+"x"+i,datas[i][0]);
        }

        // Let MXBean convert Map<String,MyCompositeData> to TabularData
        // (foo things)
        final Object cfoo = treats.getAttribute("All");
        final AttributeList afoo = treats.getAttributes(new String[] {"All"});

        // Build Map<String,MyCompositeData> with datas[i][1] (cbar)
        //
        for (int i=0;i<datas.length;i++) {
            tricks.remove(sfoop+sbarp+"x"+i);
            tricks.put(sfoop+sbarp+"x"+i,datas[i][1]);
        }

        // Let MXBean convert Map<String,MyCompositeData> to TabularData
        // (bar things)
        final Object cbar = treats.getAttribute("All");
        final AttributeList abar = treats.getAttributes(new String[] {"All"});

        // Add all datas to list
        for (int i=0;i<datas.length;i++) {
            list.add(datas[i]);
        }

        // Add converted TabularDatas to list
        list.add(new Object[] {cfoo,cbar});

        // Add AttributeList containing TabularData to list
        list.add(new Object[] {afoo,abar});

        // Add Arrays of the above to list...
        list.add(new Object[] {new Object[] {cfoo,afoo,1L},
                               new Object[] {cbar,abar,1L}});

        // Add MBeanInfo...
        list.add(new Object[] {treats.getMBeanInfo(),treats.getMBeanInfo()});

        // No ready to test conversion of all foo things into bar things.
        //
        testSerial(list.toArray(new Object[list.size()][]),
                procForFoo,procForBar);
        } catch (JMException x) {
            throw new RuntimeException(x);
        }
    }

    public static void aaaTest() {
        System.err.println("\n--------------------- aaaTest ----------------");
        System.err.println("---------------- 'foo' becomes 'bar' ---------\n");
        doSerialTest("foo","bar","foo","bar");
    }

    public static void aabTest() {
        System.err.println("\n--------------------- aabTest ----------------");
        System.err.println("---------- 'foo//bar' becomes 'bar//foo' -----\n");
        doSerialTest("foo//bar","bar//foo","foo","bar");
    }

    public static void aacTest() {
        System.err.println("\n----------------- aacTest --------------------");
        System.err.println("------------ 'foo//bar' becomes '' -----------\n");
        doSerialTest("foo//bar","","foo","bar");
    }

    public static void aadTest() {
        System.err.println("\n----------------- aadTest --------------------");
        System.err.println("----------- '' becomes 'bar//foo' ------------\n");
        doSerialTest("","bar//foo","","bar//foo");
    }

    public static void aaeTest() {
        System.err.println("\n----------------- aaeTest --------------------");
        System.err.println("----------------- '' becomes '' --------------\n");
        doSerialTest("","","foo","bar//foo");
    }

    // Let's be wild...
    public static void aafTest() {
        System.err.println("\n----------------- aafTest --------------------");
        System.err.println("----------- '' becomes '' -- (bis) -----------\n");
        doSerialTest("","","","");
    }
    public static void aagTest() {
        System.err.println("\n----------------- aagTest --------------------");
        System.err.println("----------- foobar becomes foobar ------------\n");
        doSerialTest("foobar","foobar","foobar","foobar");
    }

    // TODO add test with descriptor, MBeanInfo, Open Types, etc...
    public static void main(String[] args) {
        aaaTest();
        aabTest();
        aacTest();
        aadTest();
        aaeTest();
        aafTest();
        aagTest();

        // TODO: add a test case to test *exactly* the serialization
        // of Notification and AttributeChangeNotification, and not of
        // a subclass of these.
        // This will involve implementing some hack, because we
        // can't use equals() to compare the results.
    }
}