/*
 *
 *  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
 *
 */

package com.oracle.tests.jdk.dio.DeviceMgmtPermission;

import jdk.dio.DeviceException;
import com.sun.tck.cldc.lib.MultiTest;
import com.sun.tck.cldc.lib.Status;



import jdk.dio.DeviceMgmtPermission;

import java.security.PermissionCollection;



public class DeviceMgmtPermissionTests extends MultiTest {
    /**
     * The target name is a combination of a device name and of a device ID or range of device IDs. It takes the following form:
     * <p/>
     * {device-name-spec} [ ":"{device-id-spec} ]
     * {device-name-spec}
     * The {device-name-spec} string takes the following form:
     * {device-name} | "*" | ""
     * The {device-name}string is a device name as may be returned by a call to DeviceDescriptor.getName.
     * A {device-name-spec} specification consisting of the asterisk ("*") matches all device names. A {device-name-spec}
     * specification consisting of the empty string ("") designates an undefined device name that may only be matched by
     * an empty string or an asterisk.
     * <p/>
     * The {device-id-spec} string takes the following form:
     * {device-id} | "-"{device-id} | {device-id}"-"[{device-id}] | "*"
     */


    private String[] ok_device_name_spec = new String[]{"*", ""};
    private String[] ok_device_name = new String[]{"", "a", ":Hello:World::", "*", "***"};
    private String[] ok_device_id_spec = new String[]{
            "*", "0", "100", "" + Integer.MAX_VALUE,
            "-0", "-50", "-" + Integer.MAX_VALUE,
            "0-", "25-", Integer.MAX_VALUE + "-",
            "0-" + Integer.MAX_VALUE,
            "1-350",
            "15-15",
            "17-13"
    };

    private String[] ok_actions = new String[]{"open,register,unregister", "open,unregister", "register,open", "register"};

    /**
     * java.lang.NullPointerException - if name is null.
     */
    
    
    public Status testConstrNameNull() {
        for (String action : ok_actions) {
            try {
                new DeviceMgmtPermission(null, action);
                return Status.failed("new DeviceMgmtPermission(null, " + action + "), NPE is expected");
            } catch (NullPointerException expected) {
            }
        }

        return Status.passed("OKAY");
    }


    /**
     * java.lang.IllegalArgumentException - if actions is null, empty or contains an action other than the specified possible actions.
     */
    
    
    public Status testConstrActionsIAE() {
        for (String name : ok_device_name_spec) {
            for (String id : ok_device_id_spec) {
                try {
                    new DeviceMgmtPermission(name + ":" + id, null);
                    return Status.failed("new DeviceMgmtPermission(" + name + ":" + id + ", null), IAE is expected");
                } catch (IllegalArgumentException expected) {
                }

                try {
                    new DeviceMgmtPermission(name + ":" + id, "");
                    return Status.failed("new DeviceMgmtPermission(" + name + ":" + id + ", \"\"), IAE is expected");
                } catch (IllegalArgumentException expected) {
                }

                try {
                    new DeviceMgmtPermission(name + ":" + id, "unknown");
                    return Status.failed("new DeviceMgmtPermission(" + name + ":" + id + ", \"unknown\"), IAE is expected");
                } catch (IllegalArgumentException expected) {
                }

                for (String ok_action : ok_actions) {
                    try {
                        new DeviceMgmtPermission(name + ":" + id, "unknown" + "," + ok_action);
                        return Status.failed("new DeviceMgmtPermission(" + name + ":" + id + "unknown" + "," + ok_action + "\"), IAE is expected");
                    } catch (IllegalArgumentException expected) {
                    }

                    try {
                        new DeviceMgmtPermission(name + ":" + id, ok_action + ", unknown");
                        return Status.failed("new DeviceMgmtPermission(" + name + ":" + id + ", " + ok_action + ", unknown\"), IAE is expected");
                    } catch (IllegalArgumentException expected) {
                    }

                    try {
                        new DeviceMgmtPermission(name + ":" + id, "," + ok_action + ",");
                        return Status.failed("new DeviceMgmtPermission(" + name + ":" + id + "," + ok_action + ",\"), IAE is expected");
                    } catch (IllegalArgumentException expected) {
                    }

                }

            }
        }

        return Status.passed("OKAY");
    }

    /**
     * Constructs a new DeviceMgmtPermission instance with the specified target name and action list.
     */
    
    
    public Status testConstrOk() {
        for (String name : ok_device_name) {
            for (String id : ok_device_id_spec) {
                for (String ok_action : ok_actions) {
                    new DeviceMgmtPermission(name + ":" + id, ok_action);
                }

            }
        }

        return Status.passed("OKAY");
    }

    /**
     * The target name "*:*" matches all device names and all device IDs as is the target name "*"
     */
    
    
    public Status testConstrOk1() {
        for (String name : ok_device_name_spec) {
            for (String id : ok_device_id_spec) {
                for (String ok_action : ok_actions) {
                    new DeviceMgmtPermission(name + ":" + id, ok_action);
                }

            }
        }

        return Status.passed("OKAY");
    }


    /**
     * The target name is a combination of a device name and of a device ID or range of device IDs. It takes the following form:
     * <p/>
     * {device-name-spec} [ ":"{device-id-spec} ]
     */
    
    
    public Status testConstrOk2() {
        for (String name : ok_device_name_spec) {
            for (String ok_action : ok_actions) {
                new DeviceMgmtPermission(name, ok_action);
            }
        }
        return Status.passed("OKAY");
    }

    /**
     *
     */
    
    
    public Status testEqualsSameObj() {
        for (String name : ok_device_name) {
            for (String id : ok_device_id_spec) {
                for (String ok_action : ok_actions) {
                    DeviceMgmtPermission p1 = new DeviceMgmtPermission(name + ":" + id, ok_action);
                    DeviceMgmtPermission p2 = new DeviceMgmtPermission(name + ":" + id, ok_action);

                    if (!p1.equals(p1)) {
                        log.println(p1);
                        return Status.failed("!this.equals(this)");
                    }

                    if (p1.hashCode() != p1.hashCode()) {
                        return Status.failed("this.hashCode() returned different values on consequent calls");
                    }


                    if (!p1.equals(p2)) {
                        log.println(p1);
                        log.println(p2);
                        return Status.failed("Two DMP instances aren't equal unexpectedly");
                    }

                    if (p1.hashCode() != p2.hashCode()) {
                        log.println(p1);
                        log.println(p2);
                        return Status.failed("Two equal DMP instances, hashCode() return values are different");
                    }


                }

            }
        }

        return Status.passed("OKAY");
    }


    
    
    public Status testEqualsActionsOrder() {
        DeviceMgmtPermission p1 = new DeviceMgmtPermission("hello", "register,open,unregister");
        DeviceMgmtPermission p2 = new DeviceMgmtPermission("hello", "register,unregister,register,open");

        if (!p1.equals(p2)) {
            log.println(p1);
            log.println(p2);
            return Status.failed("Two DMP instances aren't equal unexpectedly");
        }

        return Status.passed("OKAY");
    }

    
    
    public Status testEqualsDifferentActionsNeg() {
        DeviceMgmtPermission p1 = new DeviceMgmtPermission("hello1", "register,open,unregister");
        DeviceMgmtPermission p2 = new DeviceMgmtPermission("hello", "unregister,open");

        if (p1.equals(p2)) {
            log.println(p1);
            log.println(p2);
            return Status.failed("Two DMP instances are equal unexpectedly");
        }

        return Status.passed("OKAY");
    }


    
    
    public Status testEqualsAsterisks() {
        DeviceMgmtPermission p1 = new DeviceMgmtPermission("*", "register,open,unregister");
        DeviceMgmtPermission p2 = new DeviceMgmtPermission("*:*", "register,unregister,open");
        DeviceMgmtPermission p3 = new DeviceMgmtPermission("", "unregister,open,register");
        DeviceMgmtPermission p4 = new DeviceMgmtPermission("", "unregister,register,open,open");

        if (p1.equals(p2)) {
            log.println(p1);
            log.println(p2);
            return Status.failed("(1) unexpectedly equal!");
        }

        if (!p3.equals(p4)) {
            log.println(p3);
            log.println(p4);
            return Status.failed("(2) unexpectedly are not equal");
        }

        return Status.passed("OKAY");
    }


    
    
    public Status testGetActions1() {
        String[] actions = new String[]{
                "register", "open", "unregister"
        };

        for (int i = 0; i < actions.length; i++) {
            DeviceMgmtPermission p1 = new DeviceMgmtPermission("Good, and readable, name", actions[i]);
            if (!actions[i].equals(p1.getActions())) {
                return Status.failed("Returned(" + i + "): " + p1.getActions());
            }
        }

        return Status.passed("OKAY");
    }


    
    
    public Status testGetActions2() {
        String[][] actions = new String[][]{
                new String[]{"open,register", "register,open"},
                new String[]{"register,open", "register,open"},
                new String[]{"open,unregister", "unregister,open"},
                new String[]{"unregister,register", "register,unregister"},
                new String[]{"open,unregister,register", "register,unregister,open"},
                new String[]{"unregister,register,open", "register,unregister,open"},

        };

        for (int i = 0; i < actions.length; i++) {
            DeviceMgmtPermission p1 = new DeviceMgmtPermission("Good, and readable, name", actions[i][0]);
            if (!actions[i][1].equals(p1.getActions())) {
                return Status.failed("Returned(" + i + "): " + p1.getActions());
            }
        }

        return Status.passed("OKAY");
    }


    
    
    public Status testNewPC() {
        PermissionCollection pc = null;
        for (String name : ok_device_name) {
            for (String id : ok_device_id_spec) {
                for (String ok_action : ok_actions) {
                    pc = (new DeviceMgmtPermission(name + ":" + id, ok_action)).newPermissionCollection();
                }
            }
        }

        log.println("Last recent call to NPC returns: " + pc);
        return Status.passed("OKAY");
    }


    
    
    public Status testImpliesAsterisk() {
        DeviceMgmtPermission max1 = new DeviceMgmtPermission("*:*", "register,unregister,open");
        DeviceMgmtPermission max2 = new DeviceMgmtPermission("*", "register,unregister,open");

        for (String name : ok_device_name) {
            for (String id : ok_device_id_spec) {
                for (String ok_action : ok_actions) {
                    DeviceMgmtPermission dp = new DeviceMgmtPermission(name + ":" + id, ok_action);
                    if (!max1.implies(dp)) {
                        return Status.failed("(1) maximal permission doesn't imply new DeviceMgmtPermission(" + name + ":" + id + ", " + ok_action + ")");
                    }

                    if (!max2.implies(dp)) {
                        return Status.failed("(1) maximal permission doesn't imply new DeviceMgmtPermission(" + name + ":" + id + ", " + ok_action + ")");
                    }

                }
            }
        }

        DeviceMgmtPermission almostMax = new DeviceMgmtPermission("*:-" + Integer.MAX_VALUE, "register,unregister,open");
        if (!max1.implies(almostMax)) {
            return Status.failed("(1) maximal permission doesn't imply new DeviceMgmtPermission(*:-" + Integer.MAX_VALUE + ", \"register,unregister,open\")");
        }

        if (!max2.implies(almostMax)) {
            return Status.failed("(1) maximal permission doesn't imply new DeviceMgmtPermission(*:-" + Integer.MAX_VALUE + ", \"register,unregister,open\")");
        }


        if (!max1.implies(max2)) {
            return Status.failed("*:* doesn't imply *");
        }

        if (!max2.implies(max1)) {
            return Status.failed("* doesn't imply *:*");
        }


        return Status.passed("OKAY");
    }


    
    
    public Status testImpliesSameObj() {
        for (String name : ok_device_name) {
            for (String id : ok_device_id_spec) {
                for (String ok_action : ok_actions) {
                    DeviceMgmtPermission p1 = new DeviceMgmtPermission(name + ":" + id, ok_action);
                    DeviceMgmtPermission p2 = new DeviceMgmtPermission(name + ":" + id, ok_action);

                    if (!p1.implies(p1)) {
                        log.println(p1);
                        return Status.failed("!this.implies(this)");
                    }

                    if (!p1.implies(p2)) {
                        log.println(p1);
                        log.println(p2);
                        return Status.failed("Two DMP instances don't imply each other");
                    }
                }

            }
        }

        return Status.passed("OKAY");
    }


    
    
    public Status testImpliesIDs() {
        String actions = "register";
        DeviceMgmtPermission[] dmp = new DeviceMgmtPermission[]{
                new DeviceMgmtPermission("NAME:0", actions),
                new DeviceMgmtPermission("NAME:0-0", actions),
                new DeviceMgmtPermission("NAME:1-0", actions),
                new DeviceMgmtPermission("NAME:-120", actions),
                new DeviceMgmtPermission("NAME:10-20", actions),
                new DeviceMgmtPermission("NAME:17-35", actions),
                new DeviceMgmtPermission("NAME:15-" + Integer.MAX_VALUE, actions),
        };

        boolean[][] expectedImplies = new boolean[][] {
                {true, true, true, false, false, false, false },
                {true, true, true, false, false, false, false },
                {true, true, true, false, false, false, false },
                {true, true, true, true,  true, true, false },
                {true, true, true, false, true, false, false },
                {true, true, true, false, false, true, false },
                {true, true, true, false, false, true, true}
        };



        Status[] s = new Status[]{Status.passed("OKAY")};

        for (int i = 0; i < dmp.length; i++) {
            for (int j = 0; j < dmp.length; j++) {
                if (!checkImplies(expectedImplies[i][j], dmp[i], dmp[j], s)) {
                    return s[0];
                }
            }
        }

        return Status.passed("OKAY");
    }

    private boolean checkImplies(boolean expectedResult, DeviceMgmtPermission thisPerm, DeviceMgmtPermission otherPerm, Status[] s) {
        if (expectedResult != thisPerm.implies(otherPerm)) {
            s[0] = Status.failed("\"" + thisPerm.getName() + "\" " + (expectedResult ? "doesn't imply" : "implies ") + "  \"" + otherPerm.getName() + "\"");
            return false;
        }

        return true;
    }

    
    
    public Status testImpliesNames() {
        String actions = "open";
        DeviceMgmtPermission[] dmp = new DeviceMgmtPermission[]{
                new DeviceMgmtPermission(":10-20", actions),
                new DeviceMgmtPermission("NAME:10-20", actions),
        };

        boolean[][] expectedImplies = new boolean[][] {
                {true, false},
                {false, true},
        };

        Status[] s = new Status[]{Status.passed("OKAY")};

        for (int i = 0; i < dmp.length; i++) {
            for (int j = 0; j < dmp.length; j++) {
                if (!checkImplies(expectedImplies[i][j], dmp[i], dmp[j], s)) {
                    return s[0];
                }
            }
        }

        return Status.passed("OKAY");
    }

    
    
    public Status testImpliesActions() {
        String permName = "Permission:42";
        DeviceMgmtPermission[] dmp = new DeviceMgmtPermission[]{
                new DeviceMgmtPermission(permName, "open"),
                new DeviceMgmtPermission(permName, "register"),
                new DeviceMgmtPermission(permName, "unregister"),
                new DeviceMgmtPermission(permName, "open,register"),
                new DeviceMgmtPermission(permName, "register,unregister"),
                new DeviceMgmtPermission(permName, "unregister,open"),
                new DeviceMgmtPermission(permName, "register,open,unregister"),
                new DeviceMgmtPermission(permName, "unregister,register,open"),
                new DeviceMgmtPermission(permName, "unregister,register,open,register"),

        };

        boolean[][] expectedImplies = new boolean[][] {
                {true, false, false, false, false, false, false, false, false},
                {false, true,  false, false, false, false, false, false, false},
                {false, false, true, false, false, false, false, false, false},
                {true, true,  false, true, false, false, false, false, false},
                {false, true,  true, false, true, false, false, false, false},
                {false, false,  true, false, false, true, false, false, false},
                {true, true, true, true, true, true, true, true, true},
                {true, true, true, true, true, true, true, true, true},
                {true, true, true, true, true, true, true, true, true},
        };

        Status[] s = new Status[]{Status.passed("OKAY")};

        for (int i = 0; i < dmp.length; i++) {
            for (int j = 0; j < dmp.length; j++) {
                if (!checkImplies(expectedImplies[i][j], dmp[i], dmp[j], s)) {
                    return s[0];
                }
            }
        }

        return Status.passed("OKAY");
    }




    

    protected void runTestCases() {
        if (isSelected("testConstrNameNull")){
            addStatus(testConstrNameNull());
        }
        if (isSelected("testConstrActionsIAE")){
            addStatus(testConstrActionsIAE());
        }
        if (isSelected("testConstrOk")){
            addStatus(testConstrOk());
        }
        if (isSelected("testConstrOk1")){
            addStatus(testConstrOk1());
        }
        if (isSelected("testConstrOk2")){
            addStatus(testConstrOk2());
        }
        if (isSelected("testEqualsSameObj")){
            addStatus(testEqualsSameObj());
        }
        if (isSelected("testEqualsActionsOrder")){
            addStatus(testEqualsActionsOrder());
        }
        if (isSelected("testEqualsDifferentActionsNeg")){
            addStatus(testEqualsDifferentActionsNeg());
        }
        if (isSelected("testEqualsAsterisks")){
            addStatus(testEqualsAsterisks());
        }
        if (isSelected("testGetActions1")){
            addStatus(testGetActions1());
        }
        if (isSelected("testGetActions2")){
            addStatus(testGetActions2());
        }
        if (isSelected("testNewPC")){
            addStatus(testNewPC());
        }
        if (isSelected("testImpliesAsterisk")){
            addStatus(testImpliesAsterisk());
        }
        if (isSelected("testImpliesSameObj")){
            addStatus(testImpliesSameObj());
        }
        if (isSelected("testImpliesIDs")){
            addStatus(testImpliesIDs());
        }
        if (isSelected("testImpliesNames")){
            addStatus(testImpliesNames());
        }
        if (isSelected("testImpliesActions")){
            addStatus(testImpliesActions());
        }
    }


    public static void main(String argv[]) {
        DeviceMgmtPermissionTests test = new DeviceMgmtPermissionTests();
        test.run(argv, System.err, System.out).exit();
    }

}
