/*
 * Copyright 2004-2005 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 6204469 6273765
 * @summary Test various aspects of the Descriptor interface
 * @author Eamonn McManus
 * @run clean DescriptorTest
 * @run build DescriptorTest
 * @run main DescriptorTest
 */

import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import javax.management.*;

public class DescriptorTest {
    private static String failureMessage;

    // Warning: many tests here know the contents of these variables
    // so if you change them you must change the tests
    private static final String[] testFieldNames = {
        "a", "C", "aa", "int", "nul",
    };
    private static final Object[] testFieldValues = {
        "b", "D", "bb", 5, null,
    };
    private static final String[] testFieldStrings = {
        "a=b", "C=D", "aa=bb", "int=(5)", "nul=",
    };

    public static void main(String[] args) throws Exception {
        genericTests(ImmutableDescriptor.class);
        genericTests(javax.management.modelmbean.DescriptorSupport.class);
        if (failureMessage != null)
            throw new Exception("TEST FAILED: " + failureMessage);
        else
            System.out.println("Test passed");
    }

    private static void genericTests(Class<? extends Descriptor> descrClass) {
        System.out.println("--- generic tests for " + descrClass.getName() +
                           " ---");
        for (Case<Class<? extends Descriptor>, ?, ?> test :
                 genericDescriptorTests)
            test.run(descrClass);
    }

    /*
      Testing has three parts.  We take the input parameter, of type P,
      and give it to the "prepare" method.  That returns us a test
      parameter, of type T.  We give that to the "test" method.  That
      in turn returns us a check value, of type C.  We give this to the
      "check" method.  If the "check" method returns null, the test passes.
      If the "check" method returns a string, that string explains the
      test failure.  If any of the methods throws an exception, the
      test fails.
     */
    private static abstract class Case<P, T, C> {
        Case(String name) {
            this.name = name;
        }

        void run(P p) {
            System.out.println("test: " + name);
            try {
                T t = prepare(p);
                C c = test(t);
                String failed = check(c);
                if (failed != null) {
                    System.out.println("FAILED: " + name + ": " + failed);
                    failureMessage = failed;
                }
            } catch (Exception e) {
                System.out.println("FAILED: " + name + ": exception:");
                e.printStackTrace(System.out);
                failureMessage = e.toString();
            }
        }

        abstract T prepare(P p) throws Exception;
        abstract C test(T t) throws Exception;
        abstract String check(C c) throws Exception;

        private final String name;
    }

    /*
      Test case where the preparation step consists of constructing an
      instance of the given Descriptor subclass containing test values,
      then giving that to the "test" method.
    */
    private static abstract class ProtoCase<C>
            extends Case<Class<? extends Descriptor>, Descriptor, C> {

        ProtoCase(String name) {
            super(name);
        }

        Descriptor prepare(Class<? extends Descriptor> descrClass)
                throws Exception {
            Constructor<? extends Descriptor> con =
                descrClass.getConstructor(String[].class, Object[].class);
            return con.newInstance(testFieldNames, testFieldValues);
        }
    }

    /*
      Test case where the "test" method must return a value of type C
      which we will compare against the testValue parameter given to
      the test constructor.
    */
    private static abstract class ValueProtoCase<C> extends ProtoCase<C> {
        ValueProtoCase(String name, C testValue) {
            super(name);
            this.testValue = testValue;
        }

        String check(C c) {
            final boolean array = (testValue instanceof Object[]);
            final boolean equal =
                array ?
                    Arrays.deepEquals((Object[]) testValue, (Object[]) c) :
                    testValue.equals(c);
            if (equal)
                return null;
            return "wrong value: " + string(c) + " should be " +
                string(testValue);
        }

        private final C testValue;
    }

    /*
      Test case where the dontChange method does some operation on the
      test Descriptor that is not supposed to change the contents of
      the Descriptor.  This should work for both mutable and immutable
      Descriptors, since immutable Descriptors are supposed to do
      nothing (rather than throw an exception) for mutation operations
      that would not in fact change the contents.
    */
    private static abstract class UnchangedCase extends ProtoCase<Descriptor> {
        UnchangedCase(String name) {
            super(name);
        }

        Descriptor test(Descriptor d) {
            dontChange(d);
            return d;
        }

        String check(Descriptor d) {
            String[] dnames = d.getFieldNames();
            if (!strings(dnames).equals(strings(testFieldNames)))
                return "descriptor names changed: " + strings(dnames);
            Object[] values = d.getFieldValues(testFieldNames);
            if (values.length != testFieldValues.length)
                return "getFieldValues: bogus length: " + values.length;
            for (int i = 0; i < values.length; i++) {
                Object expected = testFieldValues[i];
                Object found = values[i];
                if ((expected == null) ?
                        found != null :
                        !expected.equals(found))
                    return "descriptor value changed: " + testFieldNames[i] +
                        " was " + expected + " now " + found;
            }
            return null;
        }

        abstract void dontChange(Descriptor d);
    }

    /*
      Test case where the change(d) method attempts to make some
      change to the Descriptor d.  The behaviour depends on whether
      the Descriptor is mutable or not.  If the Descriptor is
      immutable, then the change attempt must throw a
      RuntimeOperationsException wrapping an
      UnsupportedOperationException.  If the Descriptor is mutable,
      then the change attempt must succeed, and the Descriptor must
      then look like the fieldsAndValues parameter to the constructor.
      This is simply an alternating set of field names and corresponding
      values.  So for example if it is

      "a", "b", "x", 5

      that represents a Descriptor with fields "a" and "x" whose
      corresponding values are "x" and Integer.valueOf(5).
    */
    private static abstract class ChangedCase extends ProtoCase<Object> {
        ChangedCase(String name, Object... fieldsAndValues) {
            super(name);
            if (fieldsAndValues.length % 2 != 0)
                throw new AssertionError("test wrong: odd fieldsAndValues");
            this.fieldsAndValues = fieldsAndValues;
            this.immutableTest = new UnsupportedExceptionCase(name) {
                void provoke(Descriptor d) {
                    ChangedCase.this.change(d);
                }
            };
        }

        Object test(Descriptor d) {
            if (immutable(d))
                return immutableTest.test(d);
            else {
                change(d);
                return d;
            }
        }

        String check(Object c) {
            if (c instanceof Exception)
                return immutableTest.check((Exception) c);
            else if (!(c instanceof Descriptor)) {
                return "test returned strange value: " +
                        c.getClass() + ": " + c;
            } else {
                Descriptor d = (Descriptor) c;
                String[] names = new String[fieldsAndValues.length / 2];
                Object[] expected = new Object[names.length];
                for (int i = 0; i < fieldsAndValues.length; i += 2) {
                    names[i / 2] = (String) fieldsAndValues[i];
                    expected[i / 2] = fieldsAndValues[i + 1];
                }
                String[] foundNames = d.getFieldNames();
                if (!strings(foundNames).equals(strings(names))) {
                    return "wrong field names after change: found " +
                        strings(foundNames) + ", expected " + strings(names);
                }
                Object[] found = d.getFieldValues(names);
                if (!Arrays.deepEquals(expected, found)) {
                    return "wrong value after change: for fields " +
                        Arrays.asList(names) + " values are " +
                        Arrays.asList(found) + ", should be " +
                        Arrays.asList(expected);
                }
                return null;
            }
        }

        abstract void change(Descriptor d);

        private final Object[] fieldsAndValues;
        private final ExceptionCase immutableTest;
    }

    /*
      Test case where an operation provoke(d) on the test Descriptor d
      is supposed to provoke an exception.  The exception must be a
      RuntimeOperationsException wrapping another exception whose type
      is determined by the exceptionClass() method.
    */
    private static abstract class ExceptionCase extends ProtoCase<Exception> {

        ExceptionCase(String name) {
            super(name);
        }

        Exception test(Descriptor d) {
            try {
                provoke(d);
                return null;
            } catch (Exception e) {
                return e;
            }
        }

        String check(Exception e) {
            if (e == null)
                return "did not throw exception: " + expected();
            if (!(e instanceof RuntimeOperationsException)) {
                StringWriter sw = new StringWriter();
                PrintWriter pw = new PrintWriter(sw);
                e.printStackTrace(pw);
                pw.flush();
                return "wrong exception: " + expected() + ": found: " + sw;
            }
            Throwable cause = e.getCause();
            if (!exceptionClass().isInstance(cause))
                return "wrong wrapped exception: " + cause + ": " + expected();
            return null;
        }

        String expected() {
            return "expected " + RuntimeOperationsException.class.getName() +
                " wrapping " + exceptionClass().getName();
        }

        abstract Class<? extends Exception> exceptionClass();
        abstract void provoke(Descriptor d);
    }

    private static abstract class IllegalExceptionCase extends ExceptionCase {
        IllegalExceptionCase(String name) {
            super(name);
        }

        Class<IllegalArgumentException> exceptionClass() {
            return IllegalArgumentException.class;
        }
    }

    private static abstract class UnsupportedExceptionCase
            extends ExceptionCase {
        UnsupportedExceptionCase(String name) {
            super(name);
        }

        Class<UnsupportedOperationException> exceptionClass() {
            return UnsupportedOperationException.class;
        }
    }

    /*
      List of test cases.  We will run through these once for
      ImmutableDescriptor and once for DescriptorSupport.

      Expect a compiler [unchecked] warning for this initialization.
      Writing

          new Case<Class<? extends Descriptor>, ?, ?>[] = {...}

      would cause a compiler error since you can't have arrays of
      parameterized types unless all the parameters are just "?".
      This hack with varargs gives us a compiler warning instead.
      Writing just:

          new Case<?, ?, ?>[] = {...}

      would compile here, but not where we call test.run, since you
      cannot pass an object to the run(P) method if P is "?".
    */
    private static final Case<Class<? extends Descriptor>, ?, ?>
            genericDescriptorTests[] = constantArray(

        // TEST VALUES RETURNED BY GETTERS

        new Case<Class<? extends Descriptor>, Descriptor, Object[]>(
                "getFieldValues on empty Descriptor") {
            Descriptor prepare(Class<? extends Descriptor> c)
                    throws Exception {
                Constructor<? extends Descriptor> con =
                        c.getConstructor(String[].class);
                return con.newInstance(new Object[] {new String[0]});
            }
            Object[] test(Descriptor d) {
                return d.getFieldValues("foo", "bar");
            }
            String check(Object[] v) {
                if (v.length == 2 && v[0] == null && v[1] == null)
                    return null;
                return "value should be array with null elements: " +
                        Arrays.deepToString(v);
            }
        },

        new ValueProtoCase<Set<String>>("getFieldNames",
                                        strings(testFieldNames)) {
            Set<String> test(Descriptor d) {
                return set(d.getFieldNames());
            }
        },
        new ValueProtoCase<Set<String>>("getFields",
                                        strings(testFieldStrings)) {
            Set<String> test(Descriptor d) {
                return set(d.getFields());
            }
        },
        new ValueProtoCase<Object>("getFieldValue with exact case", "b") {
            Object test(Descriptor d) {
                return d.getFieldValue("a");
            }
        },
        new ValueProtoCase<Object>("getFieldValue with lower case for upper",
                                   "D") {
            Object test(Descriptor d) {
                return d.getFieldValue("c");
            }
        },
        new ValueProtoCase<Object>("getFieldValue with upper case for lower",
                                   "bb") {
            Object test(Descriptor d) {
                return d.getFieldValue("AA");
            }
        },
        new ValueProtoCase<Object>("getFieldValue with mixed case for lower",
                                   "bb") {
            Object test(Descriptor d) {
                return d.getFieldValue("aA");
            }
        },
        new ValueProtoCase<Set<?>>("getFieldValues with null arg",
                                   set(testFieldValues)) {
            Set<?> test(Descriptor d) {
                return set(d.getFieldValues((String[]) null));
            }
        },
        new ValueProtoCase<Object[]>("getFieldValues with not all values",
                                     new Object[] {"b", "D", 5}) {
            Object[] test(Descriptor d) {
                return d.getFieldValues("a", "c", "int");
            }
        },
        new ValueProtoCase<Object[]>("getFieldValues with all values " +
                                     "lower case",
                                     new Object[]{"bb", "D", "b", 5}) {
            Object[] test(Descriptor d) {
                return d.getFieldValues("aa", "c", "a", "int");
            }
        },
        new ValueProtoCase<Object[]>("getFieldValues with all values " +
                                     "upper case",
                                     new Object[] {5, "b", "D", "bb"}) {
            Object[] test(Descriptor d) {
                return d.getFieldValues("int", "A", "C", "AA");
            }
        },
        new ValueProtoCase<Object[]>("getFieldValues with null name",
                                     new Object[] {null}) {
            Object[] test(Descriptor d) {
                return d.getFieldValues((String) null);
            }
        },
        new ValueProtoCase<Object[]>("getFieldValues with empty name",
                                     new Object[] {null}) {
            Object[] test(Descriptor d) {
                return d.getFieldValues("");
            }
        },
        new ValueProtoCase<Object[]>("getFieldValues with no names",
                                     new Object[0]) {
            Object[] test(Descriptor d) {
                return d.getFieldValues();
            }
        },

        // TEST OPERATIONS THAT DON'T CHANGE THE DESCRIPTOR
        // Even for immutable descriptors, these are allowed

        new UnchangedCase("removeField with nonexistent field") {
            void dontChange(Descriptor d) {
                d.removeField("noddy");
            }
        },
        new UnchangedCase("removeField with null field") {
            void dontChange(Descriptor d) {
                d.removeField(null);
            }
        },
        new UnchangedCase("removeField with empty field") {
            void dontChange(Descriptor d) {
                d.removeField("");
            }
        },
        new UnchangedCase("setField leaving string unchanged") {
            void dontChange(Descriptor d) {
                d.setField("a", "b");
            }
        },
        new UnchangedCase("setField leaving int unchanged") {
            void dontChange(Descriptor d) {
                d.setField("int", 5);
            }
        },
        // We do not test whether you can do a setField/s with an
        // unchanged value but the case of the name different.
        // From the spec, that should probably be illegal, but
        // it's such a corner case that we leave it alone.

        new UnchangedCase("setFields with empty arrays") {
            void dontChange(Descriptor d) {
                d.setFields(new String[0], new Object[0]);
            }
        },
        new UnchangedCase("setFields with unchanged values") {
            void dontChange(Descriptor d) {
                d.setFields(new String[] {"a", "int"},
                            new Object[] {"b", 5});
            }
        },

        // TEST OPERATIONS THAT DO CHANGE THE DESCRIPTOR
        // For immutable descriptors, these should provoke an exception

        new ChangedCase("removeField with exact case",
                        "a", "b", "C", "D", "int", 5, "nul", null) {
            void change(Descriptor d) {
                d.removeField("aa");
            }
        },
        new ChangedCase("removeField with upper case for lower",
                        "a", "b", "C", "D", "int", 5, "nul", null) {
            void change(Descriptor d) {
                d.removeField("AA");
            }
        },
        new ChangedCase("removeField with lower case for upper",
                        "a", "b", "aa", "bb", "int", 5, "nul", null) {
            void change(Descriptor d) {
                d.removeField("c");
            }
        },
        new ChangedCase("setField keeping lower case",
                        "a", "x", "C", "D", "aa", "bb", "int", 5,
                        "nul", null) {
            void change(Descriptor d) {
                d.setField("a", "x");
            }
        },

        // spec says we should conserve the original case of the field name:
        new ChangedCase("setField changing lower case to upper",
                        "a", "x", "C", "D", "aa", "bb", "int", 5,
                        "nul", null) {
            void change(Descriptor d) {
                d.setField("A", "x");
            }
        },
        new ChangedCase("setField changing upper case to lower",
                        "a", "b", "C", "x", "aa", "bb", "int", 5,
                        "nul", null) {
            void change(Descriptor d) {
                d.setField("c", "x");
            }
        },
        new ChangedCase("setField adding new field",
                        "a", "b", "C", "D", "aa", "bb", "int", 5, "xX", "yY",
                        "nul", null) {
            void change(Descriptor d) {
                d.setField("xX", "yY");
            }
        },
        new ChangedCase("setField changing type of field",
                        "a", true, "C", "D", "aa", "bb", "int", 5,
                        "nul", null) {
            void change(Descriptor d) {
                d.setField("a", true);
            }
        },
        new ChangedCase("setField changing non-null to null",
                        "a", null, "C", "D", "aa", "bb", "int", 5,
                        "nul", null) {
            void change(Descriptor d) {
                d.setField("a", null);
            }
        },
        new ChangedCase("setField changing null to non-null",
                        "a", "b", "C", "D", "aa", "bb", "int", 5,
                        "nul", 3.14) {
            void change(Descriptor d) {
                d.setField("nul", 3.14);
            }
        },

        // TEST EXCEPTION BEHAVIOUR COMMON BETWEEN MUTABLE AND IMMUTABLE

        new IllegalExceptionCase("getFieldValue with null name") {
            void provoke(Descriptor d) {
                d.getFieldValue(null);
            }
        },
        new IllegalExceptionCase("getFieldValue with empty name") {
            void provoke(Descriptor d) {
                d.getFieldValue("");
            }
        },
        new IllegalExceptionCase("setField with null name") {
            void provoke(Descriptor d) {
                d.setField(null, "x");
            }
        },
        new IllegalExceptionCase("setField with empty name") {
            void provoke(Descriptor d) {
                d.setField("", "x");
            }
        },
        new IllegalExceptionCase("setFields with null fieldNames") {
            void provoke(Descriptor d) {
                d.setFields(null, new Object[] {"X"});
            }
        },
        new IllegalExceptionCase("setFields with null fieldValues") {
            void provoke(Descriptor d) {
                d.setFields(new String[] {"X"}, null);
            }
        },
        new IllegalExceptionCase("setFields with null fieldNames and " +
                                 "fieldValues") {
            void provoke(Descriptor d) {
                d.setFields(null, null);
            }
        },
        new IllegalExceptionCase("setFields with more fieldNames than " +
                                 "fieldValues") {
            void provoke(Descriptor d) {
                d.setFields(new String[] {"A", "B"}, new String[] {"C"});
            }
        },
        new IllegalExceptionCase("setFields with more fieldValues than " +
                                 "fieldNames") {
            void provoke(Descriptor d) {
                d.setFields(new String[] {"A"}, new String[] {"B", "C"});
            }
        },
        new IllegalExceptionCase("setFields with null element of fieldNames") {
            void provoke(Descriptor d) {
                d.setFields(new String[] {null}, new String[] {"X"});
            }
        }

    );

    static <T> T[] constantArray(T... array) {
        return array;
    }

    static String string(Object x) {
        if (x instanceof Object[])
            return Arrays.asList((Object[]) x).toString();
        else
            return String.valueOf(x);
    }

    static Set<String> strings(String... values) {
        return new TreeSet<String>(Arrays.asList(values));
    }

    static <T> Set<T> set(T[] values) {
        return new HashSet<T>(Arrays.asList(values));
    }

    static boolean immutable(Descriptor d) {
        return (d instanceof ImmutableDescriptor);
        // good enough for our purposes
    }
}
