/*
 * Copyright (c) 2015, 2023, 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
 * @bug 8142968 8253751 8262944 8314986
 * @library /test/lib
 * @build AutomaticModulesTest
 *        jdk.test.lib.util.JarUtils
 *        jdk.test.lib.util.ModuleUtils
 * @run junit AutomaticModulesTest
 * @summary Basic tests for automatic modules
 */

import java.io.IOException;
import java.lang.module.Configuration;
import java.lang.module.FindException;
import java.lang.module.InvalidModuleDescriptorException;
import java.lang.module.ModuleDescriptor;
import java.lang.module.ModuleDescriptor.Requires.Modifier;
import java.lang.module.ModuleFinder;
import java.lang.module.ModuleReference;
import java.lang.module.ResolutionException;
import java.lang.module.ResolvedModule;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import jdk.test.lib.util.JarUtils;
import jdk.test.lib.util.ModuleUtils;

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

public class AutomaticModulesTest {
    private static final Path USER_DIR = Path.of(System.getProperty("user.dir"));

    // JAR file name to expected module name / version
    static Stream<Arguments> jarNames() {
        return Stream.of(
            arguments( "foo.jar",                    "foo" ),
            arguments( "foo4j.jar",                  "foo4j" ),

            arguments( "foo1.jar",                   "foo1" ),
            arguments( "foo10.jar",                  "foo10" ),

            arguments( "foo-1.jar",                  "foo/1" ),
            arguments( "foo-1.2.jar",                "foo/1.2" ),
            arguments( "foo-1.2.3.jar",              "foo/1.2.3" ),
            arguments( "foo-1.2.3.4.jar",            "foo/1.2.3.4" ),

            arguments( "foo-10.jar",                 "foo/10" ),
            arguments( "foo-10.20.jar",              "foo/10.20" ),
            arguments( "foo-10.20.30.jar",           "foo/10.20.30" ),
            arguments( "foo-10.20.30.40.jar",        "foo/10.20.30.40" ),

            arguments( "foo-bar.jar",                "foo.bar" ),
            arguments( "foo-bar-1.jar",              "foo.bar/1" ),
            arguments( "foo-bar-1.2.jar",            "foo.bar/1.2" ),
            arguments( "foo-bar-10.jar",             "foo.bar/10" ),
            arguments( "foo-bar-10.20.jar",          "foo.bar/10.20" ),

            arguments("foo.bar1.jar",                "foo.bar1" ),
            arguments( "foo.bar10.jar",              "foo.bar10" ),

            arguments( "foo-1.2-SNAPSHOT.jar",       "foo/1.2-SNAPSHOT" ),
            arguments( "foo-bar-1.2-SNAPSHOT.jar",   "foo.bar/1.2-SNAPSHOT" ),

            arguments( "foo--bar-1.0.jar",           "foo.bar/1.0" ),
            arguments( "-foo-bar-1.0.jar",           "foo.bar/1.0" ),
            arguments( "foo-bar--1.0.jar",           "foo.bar/1.0" )
        );
    }

    // JAR file names that do not map to a legal module name
    static Stream<String> barJarNames() {
        return Stream.of(
            ".jar",
            "_.jar",
            "foo.1.jar",
            "1foo.jar",
            "foo.1bar.jar"
        );
    }

    /**
     * Test mapping of JAR file names to module names
     */
    @ParameterizedTest
    @MethodSource("jarNames")
    public void testNames(String fn, String mid) throws IOException {
        String[] s = mid.split("/");
        String mn = s[0];
        String vs = (s.length == 2) ? s[1] : null;

        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        Path jf = dir.resolve(fn);

        // create empty JAR file
        createDummyJarFile(jf);

        // create a ModuleFinder to find modules in the directory
        ModuleFinder finder = ModuleFinder.of(dir);

        // a module with the expected name should be found
        Optional<ModuleReference> mref = finder.find(mn);
        assertTrue(mref.isPresent(), mn + " not found");

        ModuleDescriptor descriptor = mref.get().descriptor();
        assertTrue(descriptor.isAutomatic());
        assertEquals(mn, descriptor.name());
        if (vs == null) {
            assertFalse(descriptor.version().isPresent());
        } else {
            assertEquals(vs, descriptor.version().get().toString());
        }
    }

    /**
     * Test impossible mapping of JAR files to modules names
     */
    @ParameterizedTest
    @MethodSource("barJarNames")
    public void testBadNames(String fn) throws IOException {
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        Path jf = dir.resolve(fn);

        // create empty JAR file
        createDummyJarFile(jf);

        // should throw FindException
        var finder = ModuleFinder.of(dir);
        assertThrows(FindException.class, finder::findAll);
    }

    // Automatic-Module-Name attribute values and version in JAR file name
    static Stream<Arguments> automaticModuleNames() {
        return Stream.of(
            arguments( "foo",        null ),
            arguments( "foo",        "1.0" ),
            arguments( "foo.bar",    null ),
            arguments( "foo.bar",    "1.0" ),
            arguments( "class_",     null ),
            arguments( "class_",     "1.0" )
        );
    }

    // Bad Automatic-Module-Name attribute values
    static Stream<String> badAutomaticModuleNames() {
        return Stream.of(
            "",
            "666",
            "foo.class"
        );
    }

    /**
     * Test JAR files with the Automatic-Module-Name attribute
     */
    @ParameterizedTest
    @MethodSource("automaticModuleNames")
    public void testAutomaticModuleNameAttribute(String name, String vs)
        throws IOException
    {
        Manifest man = new Manifest();
        Attributes attrs = man.getMainAttributes();
        attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
        attrs.put(new Attributes.Name("Automatic-Module-Name"), name);

        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        String jar;
        if (vs == null) {
            jar = "m.jar";
        } else {
            jar = "m-" + vs + ".jar";
        }
        createDummyJarFile(dir.resolve(jar), man);

        ModuleFinder finder = ModuleFinder.of(dir);

        assertTrue(finder.findAll().size() == 1);
        assertTrue(finder.find(name).isPresent());

        ModuleReference mref = finder.find(name).get();
        ModuleDescriptor descriptor = mref.descriptor();
        assertEquals(name, descriptor.name());
        assertEquals(vs, descriptor.version()
                .map(ModuleDescriptor.Version::toString)
                .orElse(null));
    }

    /**
     * Test JAR files with the Automatic-Module-Name attribute with a value
     * that is not a legal module name.
     */
    @ParameterizedTest
    @MethodSource("badAutomaticModuleNames")
    public void testBadAutomaticModuleNameAttribute(String name) throws IOException {
        assertThrows(FindException.class, () -> testAutomaticModuleNameAttribute(name, null));
    }

    /**
     * Test all packages are exported
     */
    @Test
    public void testPackages() throws IOException {
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("m.jar"),
                           "p/C1.class", "p/C2.class", "q/C1.class");

        ModuleFinder finder = ModuleFinder.of(dir);
        Optional<ModuleReference> mref = finder.find("m");
        assertTrue(mref.isPresent(), "m not found");

        ModuleDescriptor descriptor = mref.get().descriptor();
        assertTrue(descriptor.isAutomatic());

        assertTrue(descriptor.packages().size() == 2);
        assertTrue(descriptor.packages().contains("p"));
        assertTrue(descriptor.packages().contains("q"));

        assertTrue(descriptor.exports().isEmpty());
        assertTrue(descriptor.opens().isEmpty());
    }

    /**
     * Test class files in JAR file where the entry does not correspond to a
     * legal package name.
     */
    @Test
    public void testBadPackage() throws IOException {
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("m.jar"), "p/C1.class", "p-/C2.class");

        ModuleFinder finder = ModuleFinder.of(dir);
        Optional<ModuleReference> mref = finder.find("m");
        assertTrue(mref.isPresent(), "m not found");

        ModuleDescriptor descriptor = mref.get().descriptor();
        assertTrue(descriptor.isAutomatic());

        assertTrue(descriptor.packages().size() == 1);
        assertTrue(descriptor.packages().contains("p"));

        assertTrue(descriptor.exports().isEmpty());
        assertTrue(descriptor.opens().isEmpty());
    }

    /**
     * Test non-class resources in a JAR file.
     */
    @Test
    public void testNonClassResources() throws IOException {
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("m.jar"),
                "LICENSE",
                "README",
                "WEB-INF/tags",
                "p/Type.class",
                "p/resources/m.properties");

        ModuleFinder finder = ModuleFinder.of(dir);
        Optional<ModuleReference> mref = finder.find("m");
        assertTrue(mref.isPresent(), "m not found");

        ModuleDescriptor descriptor = mref.get().descriptor();
        assertTrue(descriptor.isAutomatic());

        assertTrue(descriptor.packages().size() == 1);
        assertTrue(descriptor.packages().contains("p"));
    }

    /**
     * Test .class file in unnamed package (top-level directory)
     */
    @Test
    public void testClassInUnnamedPackage() throws IOException {
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("m.jar"), "Mojo.class");
        var finder = ModuleFinder.of(dir);
        assertThrows(FindException.class, finder::findAll);
    }

    /**
     * Test JAR file with META-INF/services configuration file
     */
    @Test
    public void testServicesConfiguration() throws IOException {
        String service = "p.S";
        String provider = "p.S1";

        Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");

        // provider class
        Path providerClass = tmpdir.resolve(provider.replace('.', '/') + ".class");
        Files.createDirectories(providerClass.getParent());
        Files.createFile(providerClass);

        // services configuration file
        Path services = tmpdir.resolve("META-INF").resolve("services");
        Files.createDirectories(services);
        Files.write(services.resolve(service), Set.of(provider));

        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);

        ModuleFinder finder = ModuleFinder.of(dir);

        Optional<ModuleReference> mref = finder.find("m");
        assertTrue(mref.isPresent(), "m not found");

        ModuleDescriptor descriptor = mref.get().descriptor();
        assertTrue(descriptor.provides().size() == 1);
        ModuleDescriptor.Provides provides = descriptor.provides().iterator().next();
        assertEquals(service, provides.service());
        assertTrue(provides.providers().size() == 1);
        assertTrue(provides.providers().contains((provider)));
    }

    // META-INF/services files that don't map to legal service names
    static Stream<Arguments> badServices() {
        return Stream.of(
            arguments( "-",  "p.S1" ),
            arguments( ".S", "p.S1" )
        );
    }

    /**
     * Test JAR file with META-INF/services configuration file with bad
     * values or names.
     */
    @ParameterizedTest
    @MethodSource("badServices")
    public void testBadServicesNames(String service, String provider)
        throws IOException
    {
        Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");
        Path services = tmpdir.resolve("META-INF").resolve("services");
        Files.createDirectories(services);
        Files.write(services.resolve(service), Set.of(provider));
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);

        Optional<ModuleReference> omref = ModuleFinder.of(dir).find("m");
        assertTrue(omref.isPresent());
        ModuleDescriptor descriptor = omref.get().descriptor();
        assertTrue(descriptor.provides().isEmpty());
    }

    // META-INF/services configuration file entries that are not legal
    static Stream<Arguments> badProviders() {
        return Stream.of(
            arguments("p.S", "-"),
            arguments("p.S", "p..S1"),
            arguments("p.S", "S1.")
        );
    }

    /**
     * Test JAR file with META-INF/services configuration file with bad
     * values or names.
     */
    @ParameterizedTest
    @MethodSource("badProviders")
    public void testBadProviderNames(String service, String provider)
        throws IOException
    {
        Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");

        // provider class
        Path providerClass = tmpdir.resolve(provider.replace('.', '/') + ".class");
        Files.createDirectories(providerClass.getParent());
        Files.createFile(providerClass);

        // services configuration file
        Path services = tmpdir.resolve("META-INF").resolve("services");
        Files.createDirectories(services);
        Files.write(services.resolve(service), Set.of(provider));

        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);

        // should throw FindException
        var finder = ModuleFinder.of(dir);
        assertThrows(FindException.class, finder::findAll);
    }

    /**
     * Test JAR file with META-INF/services configuration file listing a
     * provider that is not in the module.
     */
    @Test
    public void testMissingProviderPackage() throws IOException {
        Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");

        // services configuration file
        Path services = tmpdir.resolve("META-INF").resolve("services");
        Files.createDirectories(services);
        Files.write(services.resolve("p.S"), Set.of("q.P"));

        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        Path jarfile = dir.resolve("m.jar");
        JarUtils.createJarFile(jarfile, tmpdir);

        // FindException should be thrown with InvalidModuleDescriptorException as cause
        var finder = ModuleFinder.of(dir);
        FindException ex = assertThrows(FindException.class, () -> finder.findAll());
        Throwable cause = ex.getCause();
        assertTrue(cause instanceof InvalidModuleDescriptorException);
        var imde = (InvalidModuleDescriptorException) cause;
        assertEquals("Provider class q.P not in JAR file " + jarfile.getFileName(), imde.getMessage());
    }

    /**
     * Test that a JAR file with a Main-Class attribute results
     * in a module with a main class.
     */
    @Test
    public void testMainClass() throws IOException {
        String mainClass = "p.Main";

        Manifest man = new Manifest();
        Attributes attrs = man.getMainAttributes();
        attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
        attrs.put(Attributes.Name.MAIN_CLASS, mainClass);

        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        String entry = mainClass.replace('.', '/') + ".class";
        createDummyJarFile(dir.resolve("m.jar"), man, entry);

        ModuleFinder finder = ModuleFinder.of(dir);

        Configuration parent = ModuleLayer.boot().configuration();
        Configuration cf = resolve(parent, finder, "m");

        ModuleDescriptor descriptor = findDescriptor(cf, "m");
        assertEquals(mainClass, descriptor.mainClass().get());
    }

    // Main-Class attribute values that do not map to a legal qualified type name
    static Stream<String> badMainClasses() {
        return Stream.of(
            "p..Main",
            "p-.Main"
        );
    }

    /**
     * Test that a JAR file with a Main-Class attribute that is not a qualified
     * type name.
     */
    @ParameterizedTest
    @MethodSource("badMainClasses")
    public void testBadMainClass(String mainClass) throws IOException {
        Manifest man = new Manifest();
        Attributes attrs = man.getMainAttributes();
        attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
        attrs.put(Attributes.Name.MAIN_CLASS, mainClass);

        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        String entry = mainClass.replace('.', '/') + ".class";
        createDummyJarFile(dir.resolve("m.jar"), man, entry);

        // bad Main-Class value should be ignored
        Optional<ModuleReference> omref = ModuleFinder.of(dir).find("m");
        assertTrue(omref.isPresent());
        ModuleDescriptor descriptor = omref.get().descriptor();
        assertFalse(descriptor.mainClass().isPresent());
    }

    /**
     * Test that a JAR file with a Main-Class attribute that is not in the module
     */
    @Test
    public void testMissingMainClassPackage() throws IOException {
        Manifest man = new Manifest();
        Attributes attrs = man.getMainAttributes();
        attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
        attrs.put(Attributes.Name.MAIN_CLASS, "p.Main");

        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("m.jar"), man);

        // Main-Class should be ignored because package p is not in module
        Optional<ModuleReference> omref = ModuleFinder.of(dir).find("m");
        assertTrue(omref.isPresent());
        ModuleDescriptor descriptor = omref.get().descriptor();
        assertFalse(descriptor.mainClass().isPresent());
    }

    /**
     * Basic test of a configuration created with automatic modules.
     *   a requires b*
     *   a requires c*
     *   b*
     *   c*
     */
    @Test
    public void testConfiguration1() throws Exception {
        ModuleDescriptor descriptor1
            = ModuleDescriptor.newModule("a")
                .requires("b")
                .requires("c")
                .requires("java.base")
                .build();

        // b and c are automatic modules
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
        createDummyJarFile(dir.resolve("c.jar"), "q/T.class");

        // module finder locates a and the modules in the directory
        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
        ModuleFinder finder2 = ModuleFinder.of(dir);
        ModuleFinder finder = ModuleFinder.compose(finder1, finder2);

        Configuration parent = ModuleLayer.boot().configuration();
        Configuration cf = resolve(parent, finder, "a");

        assertTrue(cf.modules().size() == 3);
        assertTrue(cf.findModule("a").isPresent());
        assertTrue(cf.findModule("b").isPresent());
        assertTrue(cf.findModule("c").isPresent());

        ResolvedModule base = cf.findModule("java.base").get();
        assertTrue(base.configuration() == ModuleLayer.boot().configuration());
        ResolvedModule a = cf.findModule("a").get();
        ResolvedModule b = cf.findModule("b").get();
        ResolvedModule c = cf.findModule("c").get();

        // b && c only require java.base
        assertTrue(b.reference().descriptor().requires().size() == 1);
        assertTrue(c.reference().descriptor().requires().size() == 1);

        // readability

        assertTrue(a.reads().size() == 3);
        assertTrue(a.reads().contains(base));
        assertTrue(a.reads().contains(b));
        assertTrue(a.reads().contains(c));

        assertTrue(b.reads().contains(a));
        assertFalse(b.reads().contains(b));
        assertTrue(b.reads().contains(c));
        testReadAllBootModules(cf, "b");  // b reads all modules in boot layer

        assertTrue(c.reads().contains(a));
        assertTrue(c.reads().contains(b));
        assertFalse(c.reads().contains(c));
        testReadAllBootModules(cf, "c");  // c reads all modules in boot layer
    }

    /**
     * Basic test of a configuration created with automatic modules
     *   a requires b
     *   b requires c*
     *   c*
     *   d*
     */
    @Test
    public void testInConfiguration2() throws IOException {
        ModuleDescriptor descriptor1
            = ModuleDescriptor.newModule("a")
                .requires("b")
                .requires("java.base")
                .build();

        ModuleDescriptor descriptor2
            = ModuleDescriptor.newModule("b")
                .requires("c")
                .requires("java.base")
                .build();

        // c and d are automatic modules
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("c.jar"), "p/T.class");
        createDummyJarFile(dir.resolve("d.jar"), "q/T.class");

        // module finder locates a and the modules in the directory
        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
        ModuleFinder finder2 = ModuleFinder.of(dir);
        ModuleFinder finder = ModuleFinder.compose(finder1, finder2);

        Configuration parent = ModuleLayer.boot().configuration();
        Configuration cf = resolve(parent, finder, "a", "d");

        assertTrue(cf.modules().size() == 4);
        assertTrue(cf.findModule("a").isPresent());
        assertTrue(cf.findModule("b").isPresent());
        assertTrue(cf.findModule("c").isPresent());
        assertTrue(cf.findModule("d").isPresent());

        // c && d should only require java.base
        assertTrue(findDescriptor(cf, "c").requires().size() == 1);
        assertTrue(findDescriptor(cf, "d").requires().size() == 1);

        // readability

        ResolvedModule base = cf.findModule("java.base").get();
        assertTrue(base.configuration() == ModuleLayer.boot().configuration());
        ResolvedModule a = cf.findModule("a").get();
        ResolvedModule b = cf.findModule("b").get();
        ResolvedModule c = cf.findModule("c").get();
        ResolvedModule d = cf.findModule("d").get();

        assertTrue(a.reads().size() == 2);
        assertTrue(a.reads().contains(b));
        assertTrue(a.reads().contains(base));

        assertTrue(b.reads().size() == 3);
        assertTrue(b.reads().contains(c));
        assertTrue(b.reads().contains(d));
        assertTrue(b.reads().contains(base));

        assertTrue(c.reads().contains(a));
        assertTrue(c.reads().contains(b));
        assertFalse(c.reads().contains(c));
        assertTrue(c.reads().contains(d));
        testReadAllBootModules(cf, "c");   // c reads all modules in boot layer

        assertTrue(d.reads().contains(a));
        assertTrue(d.reads().contains(b));
        assertTrue(d.reads().contains(c));
        assertFalse(d.reads().contains(d));
        testReadAllBootModules(cf, "d");    // d reads all modules in boot layer
    }

    /**
     * Basic test of a configuration created with automatic modules
     *   a requires b
     *   b requires transitive c*
     *   c*
     *   d*
     */
    @Test
    public void testInConfiguration3() throws IOException {
        ModuleDescriptor descriptor1
            = ModuleDescriptor.newModule("a")
                .requires("b")
                .requires("java.base")
                .build();

        ModuleDescriptor descriptor2
            = ModuleDescriptor.newModule("b")
                .requires(Set.of(Modifier.TRANSITIVE), "c")
                .requires("java.base")
                .build();

        // c and d are automatic modules
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("c.jar"), "p/T.class");
        createDummyJarFile(dir.resolve("d.jar"), "q/T.class");

        // module finder locates a and the modules in the directory
        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
        ModuleFinder finder2 = ModuleFinder.of(dir);
        ModuleFinder finder = ModuleFinder.compose(finder1, finder2);

        Configuration parent = ModuleLayer.boot().configuration();
        Configuration cf = resolve(parent, finder, "a", "d");

        assertTrue(cf.modules().size() == 4);
        assertTrue(cf.findModule("a").isPresent());
        assertTrue(cf.findModule("b").isPresent());
        assertTrue(cf.findModule("c").isPresent());
        assertTrue(cf.findModule("d").isPresent());

        ResolvedModule base = cf.findModule("java.base").get();
        assertTrue(base.configuration() == ModuleLayer.boot().configuration());
        ResolvedModule a = cf.findModule("a").get();
        ResolvedModule b = cf.findModule("b").get();
        ResolvedModule c = cf.findModule("c").get();
        ResolvedModule d = cf.findModule("d").get();

        // c && d should only require java.base
        assertTrue(findDescriptor(cf, "c").requires().size() == 1);
        assertTrue(findDescriptor(cf, "d").requires().size() == 1);

        // readability

        assertTrue(a.reads().size() == 4);
        assertTrue(a.reads().contains(b));
        assertTrue(a.reads().contains(c));
        assertTrue(a.reads().contains(d));
        assertTrue(a.reads().contains(base));

        assertTrue(b.reads().size() == 3);
        assertTrue(b.reads().contains(c));
        assertTrue(b.reads().contains(d));
        assertTrue(b.reads().contains(base));

        assertTrue(c.reads().contains(a));
        assertTrue(c.reads().contains(b));
        assertFalse(c.reads().contains(c));
        assertTrue(c.reads().contains(d));
        testReadAllBootModules(cf, "c");   // c reads all modules in boot layer

        assertTrue(d.reads().contains(a));
        assertTrue(d.reads().contains(b));
        assertTrue(d.reads().contains(c));
        assertFalse(d.reads().contains(d));
        testReadAllBootModules(cf, "d");    // d reads all modules in boot layer
    }

    /**
     * Basic test to ensure that no automatic modules are resolved when
     * an automatic module is not a root or required by other modules.
     */
    @Test
    public void testInConfiguration4() throws IOException {
        ModuleDescriptor descriptor1
            = ModuleDescriptor.newModule("m1")
                .requires("java.base")
                .build();

        // automatic modules
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("auto1.jar"), "p1/C.class");
        createDummyJarFile(dir.resolve("auto2.jar"), "p2/C.class");
        createDummyJarFile(dir.resolve("auto3.jar"), "p3/C.class");

        // module finder locates m1 and the modules in the directory
        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
        ModuleFinder finder2 =  ModuleFinder.of(dir);
        ModuleFinder finder = ModuleFinder.compose(finder1, finder2);

        Configuration parent = ModuleLayer.boot().configuration();
        Configuration cf = resolve(parent, finder, "m1");

        // ensure that no automatic module is resolved
        assertTrue(cf.modules().size() == 1);
        assertTrue(cf.findModule("m1").isPresent());
    }

    /**
     * Basic test to ensure that if an automatic module is resolved then
     * all observable automatic modules are resolved.
     */
    @Test
    public void testInConfiguration5() throws IOException {
        // m1 requires m2
        ModuleDescriptor descriptor1
            = ModuleDescriptor.newModule("m1")
                .requires("m2").build();

        // m2 requires automatic module
        ModuleDescriptor descriptor2
            = ModuleDescriptor.newModule("m2")
                .requires("auto1")
                .build();

        // automatic modules
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("auto1.jar"), "p1/C.class");
        createDummyJarFile(dir.resolve("auto2.jar"), "p2/C.class");
        createDummyJarFile(dir.resolve("auto3.jar"), "p3/C.class");

        // module finder locates m1, m2, and the modules in the directory
        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
        ModuleFinder finder2 =  ModuleFinder.of(dir);
        ModuleFinder finder = ModuleFinder.compose(finder1, finder2);

        Configuration parent = ModuleLayer.boot().configuration();
        Configuration cf = resolve(parent, finder, "m1");

        // all automatic modules should be resolved
        assertTrue(cf.modules().size() == 5);
        assertTrue(cf.findModule("m1").isPresent());
        assertTrue(cf.findModule("m2").isPresent());
        assertTrue(cf.findModule("auto1").isPresent());
        assertTrue(cf.findModule("auto2").isPresent());
        assertTrue(cf.findModule("auto3").isPresent());

        ResolvedModule base = parent.findModule("java.base")
                                    .orElseThrow(() -> new RuntimeException());
        ResolvedModule m1 = cf.findModule("m1").get();
        ResolvedModule m2 = cf.findModule("m2").get();
        ResolvedModule auto1 = cf.findModule("auto1").get();
        ResolvedModule auto2 = cf.findModule("auto2").get();
        ResolvedModule auto3 = cf.findModule("auto3").get();

        // m1 does not read the automatic modules
        assertTrue(m1.reads().size() == 2);
        assertTrue(m1.reads().contains(m2));
        assertTrue(m1.reads().contains(base));

        // m2 should read all the automatic modules
        assertTrue(m2.reads().size() == 4);
        assertTrue(m2.reads().contains(auto1));
        assertTrue(m2.reads().contains(auto2));
        assertTrue(m2.reads().contains(auto3));
        assertTrue(m2.reads().contains(base));

        assertTrue(auto1.reads().contains(m1));
        assertTrue(auto1.reads().contains(m2));
        assertFalse(auto1.reads().contains(auto1));
        assertTrue(auto1.reads().contains(auto2));
        assertTrue(auto1.reads().contains(auto3));
        assertTrue(auto1.reads().contains(base));

        assertTrue(auto2.reads().contains(m1));
        assertTrue(auto2.reads().contains(m2));
        assertTrue(auto2.reads().contains(auto1));
        assertFalse(auto2.reads().contains(auto2));
        assertTrue(auto2.reads().contains(auto3));
        assertTrue(auto2.reads().contains(base));

        assertTrue(auto3.reads().contains(m1));
        assertTrue(auto3.reads().contains(m2));
        assertTrue(auto3.reads().contains(auto1));
        assertTrue(auto3.reads().contains(auto2));
        assertFalse(auto3.reads().contains(auto3));
        assertTrue(auto3.reads().contains(base));
    }

    /**
     * Basic test of automatic modules in a child configuration. All automatic
     * modules that are found with the before finder should be resolved. The
     * automatic modules that are found by the after finder and not shadowed
     * by the before finder, or parent configurations, should also be resolved.
     */
    @Test
    public void testInConfiguration6() throws IOException {
        // m1 requires auto1
        ModuleDescriptor descriptor1
            = ModuleDescriptor.newModule("m1")
                .requires("auto1")
                .build();

        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("auto1.jar"), "p1/C.class");

        // module finder locates m1 and auto1
        ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
        ModuleFinder finder2 =  ModuleFinder.of(dir);
        ModuleFinder finder = ModuleFinder.compose(finder1, finder2);

        Configuration parent = ModuleLayer.boot().configuration();
        Configuration cf1 = resolve(parent, finder, "m1");

        assertTrue(cf1.modules().size() == 2);
        assertTrue(cf1.findModule("m1").isPresent());
        assertTrue(cf1.findModule("auto1").isPresent());

        ResolvedModule base = parent.findModule("java.base")
                                    .orElseThrow(() -> new RuntimeException());
        ResolvedModule m1 = cf1.findModule("m1").get();
        ResolvedModule auto1 = cf1.findModule("auto1").get();

        assertTrue(m1.reads().size() == 2);
        assertTrue(m1.reads().contains(auto1));
        assertTrue(m1.reads().contains(base));

        assertTrue(auto1.reads().contains(m1));
        assertTrue(auto1.reads().contains(base));


        // create child configuration - the after finder locates auto1

        dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("auto2.jar"), "p2/C.class");
        ModuleFinder beforeFinder =  ModuleFinder.of(dir);

        dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("auto1.jar"), "p1/C.class");
        createDummyJarFile(dir.resolve("auto2.jar"), "p2/C.class");
        createDummyJarFile(dir.resolve("auto3.jar"), "p3/C.class");
        ModuleFinder afterFinder =  ModuleFinder.of(dir);

        Configuration cf2 = cf1.resolve(beforeFinder, afterFinder, Set.of("auto2"));

        // auto1 should be found in parent and should not be in cf2
        assertTrue(cf2.modules().size() == 2);
        assertTrue(cf2.findModule("auto2").isPresent());
        assertTrue(cf2.findModule("auto3").isPresent());

        ResolvedModule auto2 = cf2.findModule("auto2").get();
        ResolvedModule auto3 = cf2.findModule("auto3").get();

        assertTrue(auto2.reads().contains(m1));
        assertTrue(auto2.reads().contains(auto1));
        assertFalse(auto2.reads().contains(auto2));
        assertTrue(auto2.reads().contains(auto3));
        assertTrue(auto2.reads().contains(base));

        assertTrue(auto3.reads().contains(m1));
        assertTrue(auto3.reads().contains(auto1));
        assertTrue(auto3.reads().contains(auto2));
        assertFalse(auto3.reads().contains(auto3));
        assertTrue(auto3.reads().contains(base));
    }

    /**
     * Basic test for a module requiring an automatic module in a parent
     * configuration. If an explicit module in a child configuration reads an
     * automatic module in a parent configuration then it should read all
     * automatic modules in the parent configuration.
     */
    @Test
    public void testInConfiguration7() throws Exception {
        // m1 requires auto1
        ModuleDescriptor descriptor1 = ModuleDescriptor.newModule("m1")
                .requires("auto1")
                .build();

        Path dir1 = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir1.resolve("auto1.jar"), "p1/C.class");
        createDummyJarFile(dir1.resolve("auto2.jar"), "p2/C.class");

        // module finder locates m1, auto1, and auto2
        ModuleFinder finder1 = ModuleFinder.compose(ModuleUtils.finderOf(descriptor1),
                                                    ModuleFinder.of(dir1));

        Configuration parent = ModuleLayer.boot().configuration();
        ResolvedModule base = parent.findModule("java.base").orElseThrow();

        Configuration cf1 = resolve(parent, finder1, "m1");
        assertTrue(cf1.modules().size() == 3);

        ResolvedModule m1 = cf1.findModule("m1").orElseThrow();
        ResolvedModule auto1 = cf1.findModule("auto1").orElseThrow();
        ResolvedModule auto2 = cf1.findModule("auto2").orElseThrow();

        assertTrue(m1.reads().size() == 3);
        assertTrue(m1.reads().contains(base));
        assertTrue(m1.reads().contains(auto1));
        assertTrue(m1.reads().contains(auto2));

        assertTrue(auto1.reads().contains(base));
        assertTrue(auto1.reads().contains(m1));
        assertFalse(auto1.reads().contains(auto1));
        assertTrue(auto1.reads().contains(auto2));

        assertTrue(auto2.reads().contains(base));
        assertTrue(auto2.reads().contains(m1));
        assertTrue(auto2.reads().contains(auto1));
        assertFalse(auto2.reads().contains(auto2));

        // m2 requires auto1
        ModuleDescriptor descriptor2 = ModuleDescriptor.newModule("m2")
                .requires("auto1")
                .build();

        Path dir2 = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir1.resolve("auto3.jar"), "p3/C.class");

        // module finder locates m2 and auto3
        ModuleFinder finder2 = ModuleFinder.compose(ModuleUtils.finderOf(descriptor2),
                                                    ModuleFinder.of(dir2));

        Configuration cf2 = resolve(cf1, finder2, "m2");
        assertTrue(cf2.modules().size() == 1);   // auto3 should not be resolved

        ResolvedModule m2 = cf2.findModule("m2").orElseThrow();

        assertTrue(m2.reads().size() == 3);
        assertTrue(m2.reads().contains(base));
        assertTrue(m2.reads().contains(auto1));
        assertTrue(m2.reads().contains(auto2));
    }

    /**
     * Basic test of a configuration created with automatic modules
     *   a requires b* and c*
     *   b* contains p
     *   c* contains p
     */
    @Test
    public void testDuplicateSuppliers1() throws IOException {
        ModuleDescriptor descriptor
            = ModuleDescriptor.newModule("a")
                .requires("b")
                .requires("c")
                .build();

        // c and d are automatic modules with the same package
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
        createDummyJarFile(dir.resolve("c.jar"), "p/T.class");

        // module finder locates 'a' and the modules in the directory
        ModuleFinder finder
            = ModuleFinder.compose(ModuleUtils.finderOf(descriptor),
                                   ModuleFinder.of(dir));

        Configuration parent = ModuleLayer.boot().configuration();
        assertThrows(ResolutionException.class, () -> resolve(parent, finder, "a"));
    }

    /**
     * Basic test of a configuration created with automatic modules
     *   a contains p, requires b*
     *   b* contains p
     */
    @Test
    public void testDuplicateSuppliers2() throws IOException {
        ModuleDescriptor descriptor
            = ModuleDescriptor.newModule("a")
                .packages(Set.of("p"))
                .requires("b")
                .build();

        // c and d are automatic modules with the same package
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("b.jar"), "p/T.class");

        // module finder locates 'a' and the modules in the directory
        ModuleFinder finder
            = ModuleFinder.compose(ModuleUtils.finderOf(descriptor),
                                   ModuleFinder.of(dir));

        Configuration parent = ModuleLayer.boot().configuration();
        assertThrows(ResolutionException.class, () -> resolve(parent, finder, "a"));
    }

    /**
     * Basic test of layer containing automatic modules
     */
    @Test
    public void testInLayer() throws IOException {
        ModuleDescriptor descriptor
            = ModuleDescriptor.newModule("a")
                .requires("b")
                .requires("c")
                .build();

        // b and c are simple JAR files
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
        createDummyJarFile(dir.resolve("c.jar"), "q/T2.class");

        // module finder locates a and the modules in the directory
        ModuleFinder finder
            = ModuleFinder.compose(ModuleUtils.finderOf(descriptor),
                ModuleFinder.of(dir));

        Configuration parent = ModuleLayer.boot().configuration();
        Configuration cf = resolve(parent, finder, "a");
        assertTrue(cf.modules().size() == 3);

        // each module gets its own loader
        ModuleLayer layer = ModuleLayer.boot().defineModules(cf, mn -> new ClassLoader() { });

        // an unnamed module
        Module unnamed = (new ClassLoader() { }).getUnnamedModule();

        Module b = layer.findModule("b").get();
        assertTrue(b.isNamed());
        assertTrue(b.canRead(unnamed));
        testsReadsAll(b, layer);

        Module c = layer.findModule("c").get();
        assertTrue(c.isNamed());
        assertTrue(b.canRead(unnamed));
        testsReadsAll(c, layer);
    }

    /**
     * Test miscellaneous methods.
     */
    @Test
    public void testMisc() throws IOException {
        Path dir = Files.createTempDirectory(USER_DIR, "mods");
        Path m_jar = createDummyJarFile(dir.resolve("m.jar"), "p/T.class");

        ModuleFinder finder = ModuleFinder.of(m_jar);

        assertTrue(finder.find("m").isPresent());
        ModuleDescriptor m = finder.find("m").get().descriptor();

        // test miscellaneous methods
        assertTrue(m.isAutomatic());
        assertFalse(m.modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC));
    }

    /**
     * Invokes parent.resolve to resolve the given root modules.
     */
    static Configuration resolve(Configuration parent,
                                 ModuleFinder finder,
                                 String... roots) {
        return parent.resolve(finder, ModuleFinder.of(), Set.of(roots));
    }

    /**
     * Finds a module in the given configuration or its parents, returning
     * the module descriptor (or null if not found)
     */
    static ModuleDescriptor findDescriptor(Configuration cf, String name) {
        Optional<ResolvedModule> om = cf.findModule(name);
        if (om.isPresent()) {
            return om.get().reference().descriptor();
        } else {
            return null;
        }
    }

    /**
     * Test that a module in a configuration reads all modules in the boot
     * configuration.
     */
    static void testReadAllBootModules(Configuration cf, String mn) {
        Set<String> bootModules = ModuleLayer.boot().modules().stream()
                .map(Module::getName)
                .collect(Collectors.toSet());
        bootModules.forEach(other -> assertTrue(reads(cf, mn, other)));
    }

    /**
     * Test that the given Module reads all module in the given layer
     * and its parent layers.
     */
    static void testsReadsAll(Module m, ModuleLayer layer) {
        // check that m reads all modules in the layer
        layer.configuration().modules().stream()
            .map(ResolvedModule::name)
            .map(layer::findModule)
            .map(Optional::get)
            .forEach(other -> assertTrue(m.canRead(other)));

        // also check parent layers
        layer.parents().forEach(l -> testsReadsAll(m, l));
    }

    /**
     * Returns {@code true} if the configuration contains module mn1
     * that reads module mn2.
     */
    static boolean reads(Configuration cf, String mn1, String mn2) {
        Optional<ResolvedModule> om = cf.findModule(mn1);
        if (!om.isPresent())
            return false;

        return om.get().reads().stream()
                .map(ResolvedModule::name)
                .anyMatch(mn2::equals);
    }

    /**
     * Creates a JAR file, optionally with a manifest, and with the given
     * entries. The entries will be empty in the resulting JAR file.
     */
    static Path createDummyJarFile(Path jarfile, Manifest man, String... entries)
        throws IOException
    {
        Path dir = Files.createTempDirectory(USER_DIR, "tmp");

        for (String entry : entries) {
            Path file = dir.resolve(entry);
            Path parent = file.getParent();
            if (parent != null)
                Files.createDirectories(parent);
            Files.createFile(file);
        }

        Path[] paths = Stream.of(entries).map(Path::of).toArray(Path[]::new);
        JarUtils.createJarFile(jarfile, man, dir, paths);
        return jarfile;
    }

    /**
     * Creates a JAR file and with the given entries. The entries will be empty
     * in the resulting JAR file.
     */
    static Path createDummyJarFile(Path jarfile, String... entries)
        throws IOException
    {
        return createDummyJarFile(jarfile, null, entries);
    }
}
