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

/*
 * @test
 * @summary Test ScopedValue API
 * @run junit ScopedValueAPI
 */

import java.lang.ScopedValue.CallableOp;
import java.util.NoSuchElementException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.function.Supplier;
import java.util.stream.Stream;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.*;

class ScopedValueAPI {

    private static Stream<ThreadFactory> factories() {
        return Stream.of(Thread.ofPlatform().factory(), Thread.ofVirtual().factory());
    }

    /**
     * Test that where invokes the Runnable's run method.
     */
    @ParameterizedTest
    @MethodSource("factories")
    void testRunWhere(ThreadFactory factory) throws Exception {
        test(factory, () -> {
            class Box { static boolean executed; }
            ScopedValue<String> name = ScopedValue.newInstance();
            ScopedValue.where(name, "duke").run(() -> { Box.executed = true; });
            assertTrue(Box.executed);
        });
    }

    /**
     * Test where when the run method throws an exception.
     */
    @ParameterizedTest
    @MethodSource("factories")
    void testRunWhereThrows(ThreadFactory factory) throws Exception {
        test(factory, () -> {
            class FooException extends RuntimeException {  }
            ScopedValue<String> name = ScopedValue.newInstance();
            Runnable op = () -> { throw new FooException(); };
            assertThrows(FooException.class, () -> ScopedValue.where(name, "duke").run(op));
            assertFalse(name.isBound());
        });
    }

    /**
     * Test that callWhere invokes the CallableOp's call method.
     */
    @ParameterizedTest
    @MethodSource("factories")
    void testCallWhere(ThreadFactory factory) throws Exception {
        test(factory, () -> {
            ScopedValue<String> name = ScopedValue.newInstance();
            String result = ScopedValue.where(name, "duke").call(name::get);
            assertEquals("duke", result);
        });
    }

    /**
     * Test callWhere when the call method throws an exception.
     */
    @ParameterizedTest
    @MethodSource("factories")
    void testCallWhereThrows(ThreadFactory factory) throws Exception {
        test(factory, () -> {
            class FooException extends RuntimeException {  }
            ScopedValue<String> name = ScopedValue.newInstance();
            CallableOp<Void, RuntimeException> op = () -> { throw new FooException(); };
            assertThrows(FooException.class, () -> ScopedValue.where(name, "duke").call(op));
            assertFalse(name.isBound());
        });
    }

    /**
     * Test get method.
     */
    @ParameterizedTest
    @MethodSource("factories")
    void testGet(ThreadFactory factory) throws Exception {
        test(factory, () -> {
            ScopedValue<String> name1 = ScopedValue.newInstance();
            ScopedValue<String> name2 = ScopedValue.newInstance();
            assertThrows(NoSuchElementException.class, name1::get);
            assertThrows(NoSuchElementException.class, name2::get);

            // where
            ScopedValue.where(name1, "duke").run(() -> {
                assertEquals("duke", name1.get());
                assertThrows(NoSuchElementException.class, name2::get);

            });
            assertThrows(NoSuchElementException.class, name1::get);
            assertThrows(NoSuchElementException.class, name2::get);

            // callWhere
            ScopedValue.where(name1, "duke").call(() -> {
                assertEquals("duke", name1.get());
                assertThrows(NoSuchElementException.class, name2::get);
                return null;
            });
            assertThrows(NoSuchElementException.class, name1::get);
            assertThrows(NoSuchElementException.class, name2::get);
        });
    }

    /**
     * Test isBound method.
     */
    @ParameterizedTest
    @MethodSource("factories")
    void testIsBound(ThreadFactory factory) throws Exception {
        test(factory, () -> {
            ScopedValue<String> name1 = ScopedValue.newInstance();
            ScopedValue<String> name2 = ScopedValue.newInstance();
            assertFalse(name1.isBound());
            assertFalse(name2.isBound());

            // where
            ScopedValue.where(name1, "duke").run(() -> {
                assertTrue(name1.isBound());
                assertFalse(name2.isBound());
            });
            assertFalse(name1.isBound());
            assertFalse(name2.isBound());

            // callWhere
            ScopedValue.where(name1, "duke").call(() -> {
                assertTrue(name1.isBound());
                assertFalse(name2.isBound());
                return null;
            });
            assertFalse(name1.isBound());
            assertFalse(name2.isBound());
        });
    }

    /**
     * Test orElse method.
     */
    @ParameterizedTest
    @MethodSource("factories")
    void testOrElse(ThreadFactory factory) throws Exception {
        test(factory, () -> {
            ScopedValue<String> name = ScopedValue.newInstance();
            assertEquals("default", name.orElse("default"));

            // where
            ScopedValue.where(name, "duke").run(() -> {
                assertEquals("duke", name.orElse("default"));
            });

            // callWhere
            ScopedValue.where(name, "duke").call(() -> {
                assertEquals("duke", name.orElse("default"));
                return null;
            });
        });
    }

    /**
     * Test orElseThrow method.
     */
    @ParameterizedTest
    @MethodSource("factories")
    void testOrElseThrow(ThreadFactory factory) throws Exception {
        test(factory, () -> {
            class FooException extends RuntimeException { }
            ScopedValue<String> name = ScopedValue.newInstance();
            assertThrows(FooException.class, () -> name.orElseThrow(FooException::new));

            // where
            ScopedValue.where(name, "duke").run(() -> {
                assertEquals("duke", name.orElseThrow(FooException::new));
            });

            // callWhere
            ScopedValue.where(name, "duke").call(() -> {
                assertEquals("duke", name.orElseThrow(FooException::new));
                return null;
            });
        });
    }

    /**
     * Test two bindings.
     */
    @ParameterizedTest
    @MethodSource("factories")
    void testTwoBindings(ThreadFactory factory) throws Exception {
        test(factory, () -> {
            ScopedValue<String> name = ScopedValue.newInstance();
            ScopedValue<Integer> age = ScopedValue.newInstance();

            // Carrier.run
            ScopedValue.where(name, "duke").where(age, 100).run(() -> {
                assertTrue(name.isBound());
                assertTrue(age.isBound());
                assertEquals("duke", name.get());
                assertEquals(100, (int) age.get());
            });
            assertFalse(name.isBound());
            assertFalse(age.isBound());

            // Carrier.call
            ScopedValue.where(name, "duke").where(age, 100).call(() -> {
                assertTrue(name.isBound());
                assertTrue(age.isBound());
                assertEquals("duke", name.get());
                assertEquals(100, (int) age.get());
                return null;
            });
            assertFalse(name.isBound());
            assertFalse(age.isBound());
        });
    }

    /**
     * Test rebinding.
     */
    @ParameterizedTest
    @MethodSource("factories")
    void testRebinding(ThreadFactory factory) throws Exception {
        test(factory, () -> {
            ScopedValue<String> name = ScopedValue.newInstance();

            // where
            ScopedValue.where(name, "duke").run(() -> {
                assertTrue(name.isBound());
                assertEquals("duke", name.get());

                ScopedValue.where(name, "duchess").run(() -> {
                    assertTrue(name.isBound());
                    assertEquals("duchess", name.get());
                });

                assertTrue(name.isBound());
                assertEquals("duke", name.get());
            });
            assertFalse(name.isBound());

            // callWhere
            ScopedValue.where(name, "duke").call(() -> {
                assertTrue(name.isBound());
                assertEquals("duke", name.get());

                ScopedValue.where(name, "duchess").call(() -> {
                    assertTrue(name.isBound());
                    assertEquals("duchess", name.get());
                    return null;
                });

                assertTrue(name.isBound());
                assertEquals("duke", name.get());
                return null;
            });
            assertFalse(name.isBound());
        });
    }

    /**
     * Test rebinding from null vaue to another value.
     */
    @ParameterizedTest
    @MethodSource("factories")
    void testRebindingFromNull(ThreadFactory factory) throws Exception {
        test(factory, () -> {
            ScopedValue<String> name = ScopedValue.newInstance();

            // where
            ScopedValue.where(name, null).run(() -> {
                assertTrue(name.isBound());
                assertNull(name.get());

                ScopedValue.where(name, "duchess").run(() -> {
                    assertTrue(name.isBound());
                    assertTrue("duchess".equals(name.get()));
                });

                assertTrue(name.isBound());
                assertNull(name.get());
            });
            assertFalse(name.isBound());

            // callWhere
            ScopedValue.where(name, null).call(() -> {
                assertTrue(name.isBound());
                assertNull(name.get());

                ScopedValue.where(name, "duchess").call(() -> {
                    assertTrue(name.isBound());
                    assertTrue("duchess".equals(name.get()));
                    return null;
                });

                assertTrue(name.isBound());
                assertNull(name.get());
                return null;
            });
            assertFalse(name.isBound());
        });
    }

    /**
     * Test rebinding to null value.
     */
    @ParameterizedTest
    @MethodSource("factories")
    void testRebindingToNull(ThreadFactory factory) throws Exception {
        test(factory, () -> {
            ScopedValue<String> name = ScopedValue.newInstance();

            // where
            ScopedValue.where(name, "duke").run(() -> {
                assertTrue(name.isBound());
                assertEquals("duke", name.get());

                ScopedValue.where(name, null).run(() -> {
                    assertTrue(name.isBound());
                    assertNull(name.get());
                });

                assertTrue(name.isBound());
                assertEquals("duke", name.get());
            });
            assertFalse(name.isBound());

            // callWhere
            ScopedValue.where(name, "duke").call(() -> {
                assertTrue(name.isBound());
                assertEquals("duke", name.get());

                ScopedValue.where(name, null).call(() -> {
                    assertTrue(name.isBound());
                    assertNull(name.get());
                    return null;
                });

                assertTrue(name.isBound());
                assertEquals("duke", name.get());
                return null;
            });
            assertFalse(name.isBound());
        });
    }

    /**
     * Test Carrier.get.
     */
    @ParameterizedTest
    @MethodSource("factories")
    void testCarrierGet(ThreadFactory factory) throws Exception {
        test(factory, () -> {
            ScopedValue<String> name = ScopedValue.newInstance();
            ScopedValue<Integer> age = ScopedValue.newInstance();

            // one scoped value
            var carrier1 = ScopedValue.where(name, "duke");
            assertEquals("duke", carrier1.get(name));
            assertThrows(NoSuchElementException.class, () -> carrier1.get(age));

            // two scoped values
            var carrier2 = carrier1.where(age, 20);
            assertEquals("duke", carrier2.get(name));
            assertEquals(20, (int) carrier2.get(age));
        });
    }

    /**
     * Test NullPointerException.
     */
    @Test
    void testNullPointerException() {
        ScopedValue<String> name = ScopedValue.newInstance();

        assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "duke"));

        assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "duke").run(() -> { }));
        assertThrows(NullPointerException.class, () -> ScopedValue.where(name, "duke").run(null));

        assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "duke").call(() -> ""));
        assertThrows(NullPointerException.class, () -> ScopedValue.where(name, "duke").call(null));

        assertThrows(NullPointerException.class, () -> name.orElse(null));
        assertThrows(NullPointerException.class, () -> name.orElseThrow(null));

        var carrier = ScopedValue.where(name, "duke");
        assertThrows(NullPointerException.class, () -> carrier.where(null, "duke"));
        assertThrows(NullPointerException.class, () -> carrier.get((ScopedValue<?>)null));
        assertThrows(NullPointerException.class, () -> carrier.run(null));
        assertThrows(NullPointerException.class, () -> carrier.call(null));
        assertThrows(NullPointerException.class, () -> carrier.run(() -> name.orElse(null)));
    }

    @FunctionalInterface
    private interface ThrowingRunnable {
        void run() throws Exception;
    }

    /**
     * Run the given task in a thread created with the given thread factory.
     * @throws Exception if the task throws an exception
     */
    private static void test(ThreadFactory factory, ThrowingRunnable task) throws Exception {
        try (var executor = Executors.newThreadPerTaskExecutor(factory)) {
            var future = executor.submit(() -> {
                task.run();
                return null;
            });
            try {
                future.get();
            } catch (ExecutionException ee) {
                Throwable cause = ee.getCause();
                if (cause instanceof Exception e)
                    throw e;
                if (cause instanceof Error e)
                    throw e;
                throw new RuntimeException(cause);
            }
        }
    }
}
