/*
 * Copyright (c) 2016, 2019, 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.
 */

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.Utils
 *        jdk.test.lib.Asserts
 *        jdk.test.lib.JDKToolFinder
 *        jdk.test.lib.JDKToolLauncher
 *        jdk.test.lib.Platform
 *        jdk.test.lib.process.*
 * @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 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},
                {"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[][] posixNonOSXSignals = {
                {"BUS",  IsSupported.YES, CanRegister.YES, CanRaise.YES, invokedXrs},
                {"INFO", IsSupported.NO, CanRegister.NO, CanRaise.NO, Invoked.NO},
        };

        Object[][] posixOSXSignals = {
                {"BUS",  IsSupported.YES, CanRegister.NO, CanRaise.NO, Invoked.NO},
                {"INFO", 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},
        };

        Object[][] combinedPosixSignals = concatArrays(posixSignals,
                                                       (Platform.isOSX() ? posixOSXSignals : posixNonOSXSignals));
        return concatArrays(commonSignals, (Platform.isWindows() ? windowsSignals : combinedPosixSignals));
    }

    // 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();
    }

}
