/*
 * Copyright (c) 2016, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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.
 */

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import org.testng.Assert;
import org.testng.TestNG;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.DataProvider;

import jdk.test.lib.Platform;
import jdk.test.lib.Utils;

import sun.misc.Signal;
import sun.misc.SignalHandler;

/*
 * @test
 * @library /test/lib
 * @modules jdk.unsupported
 *          java.base/jdk.internal.misc
 * @build jdk.test.lib.Platform jdk.test.lib.Utils
 * @run testng/othervm -Xrs -DXrs=true SunMiscSignalTest
 * @run testng/othervm SunMiscSignalTest
 * @summary sun.misc.Signal test
 */

@Test
public class SunMiscSignalTest {

    // Set to true to enable additional debug output
    static boolean debug = true;

    // True to test while running with -Xrs
    static boolean RUNNING_WITH_Xrs = Boolean.getBoolean("Xrs");

    /**
     * Print a debug message if enabled.
     *
     * @param format the format
     * @param args   the arguments
     */
    static void printf(String format, Object... args) {
        if (debug) {
            System.out.printf("    " + format, args);
        }
    }

    enum IsSupported {NO, YES}

    enum CanRegister {NO, YES}

    enum CanRaise {NO, YES}

    enum Invoked {NO, YES}

    enum RestrictedSignals {NORMAL, XRS}

    @BeforeSuite
    static void setup() {
        System.out.printf("-Xrs: %s%n", RUNNING_WITH_Xrs);
    }

    // Provider of signals to be tested with variations for -Xrs and
    // platform dependencies
    // -Xrs restricted signals signals the VM will not handle SIGINT, SIGTERM, SIGHUP and others
    @DataProvider(name = "supportedSignals")
    static Object[][] supportedSignals() {
        RestrictedSignals rs = RUNNING_WITH_Xrs ? RestrictedSignals.XRS : RestrictedSignals.NORMAL;
        CanRegister registerXrs = RUNNING_WITH_Xrs ? CanRegister.NO : CanRegister.YES;
        CanRaise raiseXrs = RUNNING_WITH_Xrs ? CanRaise.NO : CanRaise.YES;
        Invoked invokedXrs = RUNNING_WITH_Xrs ? Invoked.NO : Invoked.YES;

        Object[][] commonSignals = new Object[][]{
                {"INT",  IsSupported.YES, registerXrs, raiseXrs, invokedXrs},
                {"TERM", IsSupported.YES, registerXrs, raiseXrs, invokedXrs},
                {"ABRT", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
        };

        Object[][] posixSignals = {
                {"HUP",  IsSupported.YES, registerXrs, raiseXrs, invokedXrs},
                {"QUIT", IsSupported.YES, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"BUS",  IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"USR1", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"USR2", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"PIPE", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"ALRM", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"CHLD", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"CONT", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"TSTP", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"TTIN", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"TTOU", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"URG",  IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"XCPU", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"XFSZ", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"VTALRM", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"PROF", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"WINCH", IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"IO",   IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"SYS",   IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
        };

        Object[][] windowsSignals = {
                {"HUP",  IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"QUIT", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"BUS",  IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"USR1", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"USR2", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"PIPE", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"ALRM", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"CHLD", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"CONT", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"TSTP", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"TTIN", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"TTOU", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"URG",  IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"XCPU", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"XFSZ", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"VTALRM", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"PROF", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"WINCH", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"IO",   IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"SYS",  IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
        };

        return concatArrays(commonSignals, (Platform.isWindows() ? windowsSignals : posixSignals));
    }

    // Provider of invalid signal names
    @DataProvider(name = "invalidSunMiscSignalNames")
    Object[][] invalidSunMiscSignalNames() {
        return new Object[][]{
                {""},
                {"I"},
                {"SIG"},
                {"SIGabc"},
                {"SIGINT"},     // prefix not allowed
                {"abc"},
        };
    }

    static Object[][] concatArrays(Object[][]... arrays) {
        int l = 0;
        for (Object[][] a : arrays) {
            l += a.length;
        }

        Object[][] newArray = new Object[l][];
        l = 0;
        for (int i = 0; i < arrays.length; i++) {
            System.arraycopy(arrays[i], 0, newArray, l, arrays[i].length);
            l += arrays[i].length;
        }

        return newArray;
    }

    // Return true if the signal is one of the shutdown signals known to the VM
    private static boolean isShutdownSignal(Signal signal) {
        String name = signal.getName();
        return name.equals("INT") || name.equals("HUP") || name.equals("TERM");
    }

    /**
     * Quick verification of supported signals using sun.misc.Signal.
     *
     * @param name the signal name
     * @throws InterruptedException would be an error if thrown
     */
    @Test(dataProvider = "supportedSignals")
    static void testSunMisc(String name, IsSupported supported, CanRegister register,
                            CanRaise raise, Invoked invoked) throws InterruptedException {
        Handler h = new Handler();
        SignalHandler orig = null;
        Signal signal = null;
        try {
            signal = new Signal(name);
            Assert.assertEquals(supported, IsSupported.YES, "Unexpected support for " + name);

            Assert.assertEquals(signal.getName(), name, "getName() mismatch, ");

            Assert.assertEquals(signal.toString(), "SIG" + name, "toString() mismatch, ");

            try {
                orig = Signal.handle(signal, h);
                printf("oldHandler: %s%n", orig);
                Assert.assertEquals(CanRegister.YES, register, "Unexpected handle succeeded " + name);
                try {
                    Signal.raise(signal);
                    Assert.assertEquals(CanRaise.YES, raise, "Unexpected raise success for " + name);
                    Invoked inv = h.semaphore().tryAcquire(Utils.adjustTimeout(100L),
                            TimeUnit.MILLISECONDS) ? Invoked.YES : Invoked.NO;
                    if (!isShutdownSignal(signal)) {
                        // Normal case
                        Assert.assertEquals(inv, invoked, "handler not invoked;");
                    } else {
                        if (orig == SignalHandler.SIG_IGN) {
                            Assert.assertEquals(inv, Invoked.NO, "handler should not be invoked");
                        } else {
                            Assert.assertEquals(inv, invoked, "handler not invoked;");
                        }
                    }
                } catch (IllegalArgumentException uoe3) {
                    Assert.assertNotEquals(CanRaise.YES, raise, "raise failed for " + name +
                            ": " + uoe3.getMessage());
                }
            } catch (IllegalArgumentException uoe2) {
                Assert.assertNotEquals(CanRegister.YES, register, "handle failed for: " + name +
                        ": " + uoe2.getMessage());
            }
        } catch (IllegalArgumentException uoe) {
            Assert.assertNotEquals(IsSupported.YES, supported, "Support missing for " + name +
                    ": " + uoe.getMessage());
            return;
        } finally {
            // Restore original signal handler
            if (orig != null && signal != null) {
                Signal.handle(signal, orig);
            }
        }
    }

    // Test Signal is equal to itself and not equals to others
    @Test(dataProvider = "supportedSignals")
    static void testEquals(String name, IsSupported supported, CanRegister register,
                           CanRaise raise, Invoked invoked) {
        Object[][] data = supportedSignals();
        for (int i = 0; i < data.length; i++) {
            IsSupported otherSupported = (IsSupported) data[i][1];
            if (supported == IsSupported.NO || otherSupported == IsSupported.NO) {
                continue;
            }
            String otherName = (String) data[i][0];

            Signal sig1 = new Signal(name);
            Signal sig2 = new Signal(otherName);
            if (name.equals(otherName)) {
                Assert.assertEquals(sig1, sig2, "Equals failed; ");
                Assert.assertEquals(sig1.hashCode(), sig2.hashCode(), "HashCode wrong; ");
            } else {
                Assert.assertNotEquals(sig1, sig2, "NotEquals failed; ");
                Assert.assertNotEquals(sig1.hashCode(), sig2.hashCode(), "HashCode wrong; ");
            }
        }
    }

    @Test(dataProvider = "invalidSunMiscSignalNames")
    static void testSunMiscIAE(String name) {
        try {
            new Signal(name);
            Assert.fail("Should have thrown IAE for signal: " + name);
        } catch (IllegalArgumentException iae) {
            Assert.assertEquals(iae.getMessage(), "Unknown signal: " + name, "getMessage() incorrect; ");
        }
    }

    // Note: JDK 8 did not check/throw NPE, passing null resulted in a segv
    @Test(expectedExceptions = NullPointerException.class)
    static void nullSignal() {
        new Signal(null);
    }

    // Test expected exception when raising a signal when no handler defined
    @Test
    static void testRaiseNoConsumer() {
        Signal signal = new Signal("INT");
        SignalHandler orig = null;
        try {
            orig = Signal.handle(signal, SignalHandler.SIG_DFL);
            printf("oldHandler: %s%n", orig);
            if (orig == SignalHandler.SIG_IGN) {
                // SIG_IGN for TERM means it cannot be handled
                return;
            }
            Signal.raise(signal);
            Assert.fail("Should have thrown IllegalArgumentException");
        } catch (IllegalArgumentException iae) {
            printf("IAE message: %s%n", iae.getMessage());
        } finally {
            // Restore original signal handler
            if (orig != null && signal != null) {
                Signal.handle(signal, orig);
            }
        }
    }

    /**
     * The thread that runs the handler for sun.misc.Signal should be a
     * Daemon thread.
     */
    @Test
    static void isDaemonThread() throws InterruptedException {
        if (RUNNING_WITH_Xrs) {
            return;
        }
        Handler handler = new Handler();
        Signal signal = new Signal("INT");
        SignalHandler orig = Signal.handle(signal, handler);
        printf("oldHandler: %s%n", orig);
        if (orig == SignalHandler.SIG_IGN) {
            // SIG_IGN for INT means it cannot be handled
            return;
        }

        Signal.raise(signal);
        boolean handled = handler.semaphore()
                .tryAcquire(Utils.adjustTimeout(100L), TimeUnit.MILLISECONDS);
        if (!handled) {
            // For debug try again
            printf("Second try to see signal");
            handled = handler.semaphore()
                    .tryAcquire(Utils.adjustTimeout(2L), TimeUnit.SECONDS);
        }
        Assert.assertEquals(handled, !RUNNING_WITH_Xrs,
                "raising s.m.Signal did not get a callback;");

        Assert.assertTrue(handler.wasDaemon(), "Thread.isDaemon running the handler; ");
    }

    // Check that trying to invoke SIG_DFL.handle throws UnsupportedOperationException.
    @Test(expectedExceptions = UnsupportedOperationException.class)
    static void cannotHandleSIGDFL() {
        Signal signal = new Signal("INT");
        Assert.assertNotNull(SignalHandler.SIG_DFL, "SIG_DFL null; ");
        SignalHandler.SIG_DFL.handle(signal);
    }

    // Check that trying to invoke SIG_IGN.handle throws UnsupportedOperationException.
    @Test(expectedExceptions = UnsupportedOperationException.class)
    static void cannotHandleSIGIGN() {
        Signal signal = new Signal("INT");
        Assert.assertNotNull(SignalHandler.SIG_IGN, "SIG_IGN null; ");
        SignalHandler.SIG_IGN.handle(signal);
    }

    // Check that setting a Signal handler returns the previous handler.
    @Test()
    static void checkLastHandler() {
        if (RUNNING_WITH_Xrs) {
            return;
        }
        Signal signal = new Signal("TERM");
        Handler h1 = new Handler();
        Handler h2 = new Handler();
        SignalHandler orig = Signal.handle(signal, h1);
        if (orig == SignalHandler.SIG_IGN) {
            // SIG_IGN for TERM means it cannot be handled
            return;
        }

        try {
            SignalHandler prev = Signal.handle(signal, h2);
            Assert.assertSame(prev, h1, "prev handler mismatch");

            prev = Signal.handle(signal, h1);
            Assert.assertSame(prev, h2, "prev handler mismatch");
        } finally {
            if (orig != null && signal != null) {
                Signal.handle(signal, orig);
            }
        }
    }

    /**
     * Test Handler, a SignalHandler for Signal notifications.
     * Signals a semaphore when invoked and records whether
     * the thread calling the Handler was a daemon.
     */
    static class Handler implements SignalHandler {
        // A semaphore to check for accept being called
        Semaphore sema = new Semaphore(0);

        Boolean wasDaemon = null;

        Semaphore semaphore() {
            return sema;
        }

        synchronized Boolean wasDaemon() {
            return wasDaemon;
        }

        /**
         * Releases the semaphore when called as SignalHandler.handle.
         *
         * @param signal the Signal that occurred
         */
        @Override
        public void handle(Signal signal) {
            synchronized (this) {
                wasDaemon = Thread.currentThread().isDaemon();
            }
            sema.release();
            printf("sun.misc.handle sig: %s, num: %d%n", signal.getName(), signal.getNumber());
        }

        public String toString() {
            return "Handler: sem: " + sema.getQueueLength() +
                    ", wasDaemon: " + Objects.toString(wasDaemon());
        }
    }

    // Main can be used to run the tests from the command line with only testng.jar.
    @SuppressWarnings("raw_types")
    @Test(enabled = false)
    public static void main(String[] args) {
        Class<?>[] testclass = {SunMiscSignalTest.class};
        TestNG testng = new TestNG();
        testng.setTestClasses(testclass);
        testng.run();
    }

}
