/*
 * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2021, BELLSOFT. 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.
 */

/*
 * LoadLibraryUnload class calls ClassLoader.loadedLibrary from multiple threads
 */
/*
 * The driver for this test is LoadLibraryUnloadTest.java.
 *
 * @bug 8266310
 * @summary Loads a native library from multiple class loaders and multiple
 *          threads. This creates a race for loading the library. The winner
 *          loads the library in two threads. All threads except two would fail
 *          with UnsatisfiedLinkError when the class being loaded is already
 *          loaded in a different class loader that won the race. The test
 *          checks that the loaded class is GC'ed, that means the class loader
 *          is GC'ed and the native library is unloaded.
 */
import jdk.test.lib.Asserts;
import jdk.test.lib.Utils;

import java.lang.*;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.*;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import jdk.test.lib.util.ForceGC;

import p.Class1;

public class LoadLibraryUnload {

    private static class TestLoader extends URLClassLoader {
        public TestLoader() throws Exception {
            super(new URL[] { Path.of(System.getProperty("test.classes")).toUri().toURL() });
        }

        @Override
        public Class<?> loadClass(String name) throws ClassNotFoundException {
            synchronized (getClassLoadingLock(name)) {
                Class<?> clazz = findLoadedClass(name);
                if (clazz == null) {
                    try {
                        clazz = findClass(name);
                    } catch (ClassNotFoundException ignore) {
                    }
                    if (clazz == null) {
                        clazz = super.loadClass(name);
                    }
                }
                return clazz;
            }
        }
    }

    private static class LoadLibraryFromClass implements Runnable {
        Object object;
        Method method;
        Object canary;

        public LoadLibraryFromClass(Class<?> fromClass, Object canary) {
            try {
                this.object = fromClass.newInstance();
                this.method = fromClass.getDeclaredMethod("loadLibrary", Object.class);
                this.canary = canary;
            } catch (ReflectiveOperationException roe) {
                throw new RuntimeException(roe);
            }
        }

        @Override
        public void run() {
            try {
                method.invoke(object, canary);
            } catch (ReflectiveOperationException roe) {
                throw new RuntimeException(roe);
            }
        }
    }

    public static void main(String[] args) throws Exception {

        int LOADER_COUNT = 5;
        List<Thread> threads = new ArrayList<>();
        Object[] canary = new Object[LOADER_COUNT];
        final WeakReference<Object> wCanary[] = new WeakReference[LOADER_COUNT];

        for (int i = 0 ; i < LOADER_COUNT ; i++) {
            // LOADER_COUNT loaders and 2X threads in total.
            // winner loads the library in 2 threads
            canary[i] = new Object();
            wCanary[i] = new WeakReference<>(canary[i], null);

            Class<?> clazz = new TestLoader().loadClass("p.Class1");
            threads.add(new Thread(new LoadLibraryFromClass(clazz, canary[i])));
            threads.add(new Thread(new LoadLibraryFromClass(clazz, canary[i])));
        }

        final Set<Throwable> exceptions = ConcurrentHashMap.newKeySet();
        threads.forEach( t -> {
            t.setUncaughtExceptionHandler((th, ex) -> {
                // collect the root cause of each failure
                Throwable rootCause = ex;
                while((ex = ex.getCause()) != null) {
                    rootCause = ex;
                }
                exceptions.add(rootCause);
            });
            t.start();
        });

        // wait for all threads to finish
        for (Thread t : threads) {
            t.join();
        }

        // expect all errors to be UnsatisfiedLinkError
        boolean allAreUnsatisfiedLinkError = exceptions
                .stream()
                .map(e -> e instanceof UnsatisfiedLinkError)
                .reduce(true, (i, a) -> i && a);

        // expect exactly 8 errors
        int expectedErrorCount = (LOADER_COUNT - 1) * 2;
        Asserts.assertTrue(exceptions.size() == expectedErrorCount,
                "Expected to see " + expectedErrorCount + " failing threads");

        Asserts.assertTrue(allAreUnsatisfiedLinkError,
                "All errors have to be UnsatisfiedLinkError");

        // release strong refs
        threads = null;
        canary = null;
        exceptions.clear();

        // Wait for the canary for each of the libraries to be GC'd (cleared)
        boolean allClear = ForceGC.wait(() -> {
            for (int i = 0; i < wCanary.length; i++) {
                if (!wCanary[i].refersTo(null)) {
                    return false;
                }
            }
            return true;
        });
        Asserts.assertTrue(allClear, "Not all WeakReferences cleared");

        // Ensure the WeakReferences are strongly referenced until they can be dequeued
        Reference.reachabilityFence(wCanary);
    }
}
