/*
 * Copyright (c) 2018, 2021, 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 8247352 8293348
 * @summary test different configurations of sealed classes, same compilation unit, diff pkg or mdl, etc
 * @library /tools/lib
 * @modules jdk.compiler/com.sun.tools.javac.api
 *          jdk.compiler/com.sun.tools.javac.main
 *          jdk.compiler/com.sun.tools.javac.util
 *          jdk.compiler/com.sun.tools.javac.code
 *          jdk.jdeps/com.sun.tools.classfile
 * @build toolbox.ToolBox toolbox.JavacTask
 * @run main SealedDiffConfigurationsTest
 */

import java.util.*;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.IntStream;

import com.sun.tools.classfile.*;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.util.Assert;
import toolbox.TestRunner;
import toolbox.ToolBox;
import toolbox.JavacTask;
import toolbox.Task;
import toolbox.Task.OutputKind;

import static com.sun.tools.classfile.ConstantPool.*;

public class SealedDiffConfigurationsTest extends TestRunner {
    ToolBox tb;

    SealedDiffConfigurationsTest() {
        super(System.err);
        tb = new ToolBox();
    }

    protected void runTests() throws Exception {
        runTests(m -> new Object[] { Paths.get(m.getName()) });
    }

    public static void main(String... args) throws Exception {
        SealedDiffConfigurationsTest t = new SealedDiffConfigurationsTest();
        t.runTests();
    }

    Path[] findJavaFiles(Path... paths) throws IOException {
        return tb.findJavaFiles(paths);
    }

    @Test
    public void testSameCompilationUnitPos(Path base) throws Exception {
        Path src = base.resolve("src");
        Path test = src.resolve("Test");

        tb.writeJavaFiles(test,
                          "class Test {\n" +
                           "    sealed class Sealed permits Sub1, Sub2 {}\n" +
                           "    final class Sub1 extends Sealed {}\n" +
                           "    final class Sub2 extends Sealed {}\n" +
                           "}");

        Path out = base.resolve("out");

        Files.createDirectories(out);

        new JavacTask(tb)
                .outdir(out)
                .files(findJavaFiles(test))
                .run()
                .writeAll();

        checkSealedClassFile(out, "Test$Sealed.class", List.of("Test$Sub1", "Test$Sub2"));
        checkSubtypeClassFile(out, "Test$Sub1.class", "Test$Sealed", true);
        checkSubtypeClassFile(out, "Test$Sub2.class", "Test$Sealed", true);
    }

    @Test
    public void testSameCompilationUnitPos2(Path base) throws Exception {
        Path src = base.resolve("src");
        Path test = src.resolve("Test");

        tb.writeJavaFiles(test,
                "class Test {\n" +
                        "    sealed class Sealed {}\n" +
                        "    final class Sub1 extends Sealed {}\n" +
                        "    final class Sub2 extends Sealed {}\n" +
                        "}");

        Path out = base.resolve("out");

        Files.createDirectories(out);

        new JavacTask(tb)
                .outdir(out)
                .files(findJavaFiles(test))
                .run()
                .writeAll();

        checkSealedClassFile(out, "Test$Sealed.class", List.of("Test$Sub1", "Test$Sub2"));
        checkSubtypeClassFile(out, "Test$Sub1.class", "Test$Sealed", true);
        checkSubtypeClassFile(out, "Test$Sub2.class", "Test$Sealed", true);
    }

    private void checkSealedClassFile(Path out, String cfName, List<String> expectedSubTypeNames) throws ConstantPoolException, Exception {
        ClassFile sealedCF = ClassFile.read(out.resolve(cfName));
        Assert.check((sealedCF.access_flags.flags & Flags.FINAL) == 0, String.format("class at file %s must not be final", cfName));
        PermittedSubclasses_attribute permittedSubclasses = (PermittedSubclasses_attribute)sealedCF.attributes.get("PermittedSubclasses");
        Assert.check(permittedSubclasses.subtypes.length == expectedSubTypeNames.size());
        List<String> subtypeNames = new ArrayList<>();
        IntStream.of(permittedSubclasses.subtypes).forEach(i -> {
            try {
                subtypeNames.add(((CONSTANT_Class_info)sealedCF.constant_pool.get(i)).getName());
            } catch (ConstantPoolException ex) {
            }
        });
        for (int i = 0; i < expectedSubTypeNames.size(); i++) {
            Assert.check(expectedSubTypeNames.get(0).equals(subtypeNames.get(0)));
        }
    }

    private void checkSubtypeClassFile(Path out, String cfName, String superClassName, boolean shouldBeFinal) throws Exception {
        ClassFile subCF1 = ClassFile.read(out.resolve(cfName));
        if (shouldBeFinal) {
            Assert.check((subCF1.access_flags.flags & Flags.FINAL) != 0, String.format("class at file %s must be final", cfName));
        }
        Assert.checkNull((PermittedSubclasses_attribute)subCF1.attributes.get("PermittedSubclasses"));
        Assert.check(((CONSTANT_Class_info)subCF1.constant_pool.get(subCF1.super_class)).getName().equals(superClassName));
    }

    @Test
    public void testSamePackagePos(Path base) throws Exception {
        Path src = base.resolve("src");
        Path pkg = src.resolve("pkg");
        Path sealed = pkg.resolve("Sealed");
        Path sub1 = pkg.resolve("Sub1");
        Path sub2 = pkg.resolve("Sub2");

        tb.writeJavaFiles(sealed,
                          "package pkg;\n" +
                          "\n" +
                          "sealed class Sealed permits Sub1, Sub2 {\n" +
                          "}");
        tb.writeJavaFiles(sub1,
                          "package pkg;\n" +
                          "\n" +
                          "final class Sub1 extends Sealed {\n" +
                          "}");
        tb.writeJavaFiles(sub2,
                          "package pkg;\n" +
                          "\n" +
                          "final class Sub2 extends Sealed {\n" +
                          "}");

        Path out = base.resolve("out");

        Files.createDirectories(out);

        new JavacTask(tb)
                .outdir(out)
                .files(findJavaFiles(pkg))
                .run()
                .writeAll();

        checkSealedClassFile(out.resolve("pkg"), "Sealed.class", List.of("pkg/Sub1", "pkg/Sub1"));
        checkSubtypeClassFile(out.resolve("pkg"), "Sub1.class", "pkg/Sealed", true);
        checkSubtypeClassFile(out.resolve("pkg"), "Sub2.class", "pkg/Sealed", true);
    }

    @Test
    public void testSameCompilationUnitNeg(Path base) throws Exception {
        Path src = base.resolve("src");
        Path test = src.resolve("Test");

        tb.writeJavaFiles(test,
                          "class Test {\n" +
                           "    sealed class Sealed permits Sub1 {}\n" +
                           "    final class Sub1 extends Sealed {}\n" +
                           "    class Sub2 extends Sealed {}\n" +
                           "}");

        List<String> error = new JavacTask(tb)
                .options("-XDrawDiagnostics")
                .files(findJavaFiles(test))
                .run(Task.Expect.FAIL)
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        List<String> expected = List.of(
                "Test.java:4:5: compiler.err.cant.inherit.from.sealed: Test.Sealed",
                "1 error");
        if (!error.containsAll(expected)) {
            throw new AssertionError("Expected output not found. Expected: " + expected);
        }
    }

    @Test
    public void testSameCompilationUnitNeg2(Path base) throws Exception {
        Path src = base.resolve("src");
        Path test = src.resolve("Test");

        tb.writeJavaFiles(test,
                "class Test {\n" +
                        "    sealed class Sealed permits Sub1 {}\n" +
                        "    class Sub1 extends Sealed {}\n" +
                        "}");

        List<String> error = new JavacTask(tb)
                .options("-XDrawDiagnostics")
                .files(findJavaFiles(test))
                .run(Task.Expect.FAIL)
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        List<String> expected = List.of(
                "Test.java:3:5: compiler.err.non.sealed.sealed.or.final.expected",
                "1 error");
        if (!error.containsAll(expected)) {
            throw new AssertionError("Expected output not found. Expected: " + expected);
        }
    }

    @Test
    public void testSamePackageNeg(Path base) throws Exception {
        Path src = base.resolve("src");
        Path pkg = src.resolve("pkg");
        Path sealed = pkg.resolve("Sealed");
        Path sub1 = pkg.resolve("Sub1");
        Path sub2 = pkg.resolve("Sub2");

        tb.writeJavaFiles(sealed,
                          "package pkg;\n" +
                          "\n" +
                          "sealed class Sealed permits Sub1 {\n" +
                          "}");
        tb.writeJavaFiles(sub1,
                          "package pkg;\n" +
                          "\n" +
                          "final class Sub1 extends Sealed {\n" +
                          "}");
        tb.writeJavaFiles(sub2,
                          "package pkg;\n" +
                          "\n" +
                          "class Sub2 extends Sealed {\n" +
                          "}");

        List<String> error = new JavacTask(tb)
                .options("-XDrawDiagnostics")
                .files(findJavaFiles(pkg))
                .run(Task.Expect.FAIL)
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        List<String> expected = List.of(
                "Sub2.java:3:1: compiler.err.cant.inherit.from.sealed: pkg.Sealed",
                "1 error"
                );
        if (!error.containsAll(expected)) {
            throw new AssertionError("Expected output not found. Expected: " + expected);
        }
    }

    @Test
    public void testSamePackageNeg2(Path base) throws Exception {
        Path src = base.resolve("src");
        Path pkg = src.resolve("pkg");
        Path sealed = pkg.resolve("Sealed");
        Path sub1 = pkg.resolve("Sub1");

        tb.writeJavaFiles(sealed,
                "package pkg;\n" +
                        "\n" +
                        "final class Sealed {\n" +
                        "}");
        tb.writeJavaFiles(sub1,
                "package pkg;\n" +
                        "\n" +
                        "class Sub1 extends Sealed {\n" +
                        "}");

        List<String> error = new JavacTask(tb)
                .options("-XDrawDiagnostics")
                .files(findJavaFiles(pkg))
                .run(Task.Expect.FAIL)
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        List<String> expected = List.of(
                "Sub1.java:3:20: compiler.err.cant.inherit.from.final: pkg.Sealed",
                "1 error");
        if (!error.containsAll(expected)) {
            throw new AssertionError("Expected output not found. Expected: " + expected);
        }
    }

    @Test
    public void testSamePackageNeg3(Path base) throws Exception {
        Path src = base.resolve("src");
        Path pkg = src.resolve("pkg");
        Path sealed = pkg.resolve("Sealed");
        Path sub1 = pkg.resolve("Sub1");

        tb.writeJavaFiles(sealed,
                "package pkg;\n" +
                        "\n" +
                        "sealed class Sealed permits Sub1{\n" +
                        "}");
        tb.writeJavaFiles(sub1,
                "package pkg;\n" +
                        "\n" +
                        "class Sub1 extends Sealed {\n" +
                        "}");

        List<String> error = new JavacTask(tb)
                .options("-XDrawDiagnostics")
                .files(findJavaFiles(pkg))
                .run(Task.Expect.FAIL)
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        List<String> expected = List.of(
                "Sub1.java:3:1: compiler.err.non.sealed.sealed.or.final.expected",
                "1 error");
        if (!error.containsAll(expected)) {
            throw new AssertionError("Expected output not found. Expected: " + expected);
        }
    }

    @Test
    public void testDiffPackageNeg(Path base) throws Exception {
        Path src = base.resolve("src");
        Path pkg1 = src.resolve("pkg1");
        Path pkg2 = src.resolve("pkg2");
        Path sealed = pkg1.resolve("Sealed");
        Path sub1 = pkg2.resolve("Sub1");
        Path sub2 = pkg2.resolve("Sub2");

        tb.writeJavaFiles(sealed,
                "package pkg1;\n" +
                        "import pkg2.*;\n" +
                        "public sealed class Sealed permits pkg2.Sub1 {\n" +
                        "}");
        tb.writeJavaFiles(sub1,
                "package pkg2;\n" +
                        "import pkg1.*;\n" +
                        "public final class Sub1 extends pkg1.Sealed {\n" +
                        "}");

        List<String> error = new JavacTask(tb)
                .options("-XDrawDiagnostics")
                .files(findJavaFiles(pkg1, pkg2))
                .run(Task.Expect.FAIL)
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        List<String> expected = List.of(
                "Sealed.java:3:40: compiler.err.class.in.unnamed.module.cant.extend.sealed.in.diff.package: pkg1.Sealed",
                "1 error");
        if (!error.containsAll(expected)) {
            throw new AssertionError("Expected output not found. Expected: " + expected);
        }
    }

    @Test
    public void testDiffPackageNeg2(Path base) throws Exception {
        // test that the compiler rejects a subtype that is not accessible to the sealed class
        Path src = base.resolve("src");
        Path pkg1 = src.resolve("pkg1");
        Path pkg2 = src.resolve("pkg2");
        Path sealed = pkg1.resolve("Sealed");
        Path sub1 = pkg2.resolve("Sub1");
        Path sub2 = pkg2.resolve("Sub2");

        tb.writeJavaFiles(sealed,
                "package pkg1;\n" +
                        "import pkg2.*;\n" +
                        "public sealed class Sealed permits pkg2.Sub1 {\n" +
                        "}");
        tb.writeJavaFiles(sub1,
                "package pkg2;\n" +
                        "import pkg1.*;\n" +
                        "final class Sub1 extends pkg1.Sealed {\n" +
                        "}");

        List<String> error = new JavacTask(tb)
                .options("-XDrawDiagnostics")
                .files(findJavaFiles(pkg1, pkg2))
                .run(Task.Expect.FAIL)
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        List<String> expected = List.of(
                "Sealed.java:3:40: compiler.err.not.def.public.cant.access: pkg2.Sub1, pkg2",
                "Sub1.java:3:7: compiler.err.cant.inherit.from.sealed: pkg1.Sealed",
                "2 errors");
        if (!error.containsAll(expected)) {
            throw new AssertionError("Expected output not found. Expected: " + expected);
        }
    }

    @Test
    public void testDiffPackageNeg3(Path base) throws Exception {
        Path src = base.resolve("src");
        Path pkg1 = src.resolve("pkg1");
        Path pkg2 = src.resolve("pkg2");
        Path sealed = pkg1.resolve("Sealed");
        Path sub1 = pkg2.resolve("Sub1");
        Path sub2 = pkg2.resolve("Sub2");

        tb.writeJavaFiles(sealed,
                "package pkg1;\n" +
                        "import pkg2.*;\n" +
                        "public sealed class Sealed permits pkg2.Sub1 {\n" +
                        "}");
        tb.writeJavaFiles(sub1,
                "package pkg2;\n" +
                        "import pkg1.*;\n" +
                        "public final class Sub1 extends pkg1.Sealed {\n" +
                        "}");

        Path out = base.resolve("out");

        Files.createDirectories(out);

        List<String> error = new JavacTask(tb)
                .options("-XDrawDiagnostics")
                .files(findJavaFiles(pkg1, pkg2))
                .run(Task.Expect.FAIL)
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        List<String> expected = List.of(
                "Sealed.java:3:40: compiler.err.class.in.unnamed.module.cant.extend.sealed.in.diff.package: pkg1.Sealed",
                "1 error");
        if (!error.containsAll(expected)) {
            throw new AssertionError("Expected output not found. Found: " + error);
        }
    }

    @Test
    public void testSameModuleSamePkgPos(Path base) throws Exception {
        Path src = base.resolve("src");
        Path src_m1 = src.resolve("mSealed");
        tb.writeJavaFiles(src_m1,
                "module mSealed {}",
                "package pkg; public sealed class Sealed permits pkg.Sub{}",
                "package pkg; public final class Sub extends pkg.Sealed{}");
        Path classes = base.resolve("classes");
        tb.createDirectories(classes);

        new JavacTask(tb)
                .options("--module-source-path", src.toString())
                .outdir(classes)
                .files(findJavaFiles(src))
                .run()
                .writeAll();
    }

    @Test
    public void testSameModuleDiffPkgPos(Path base) throws Exception {
        Path src = base.resolve("src");
        Path src_m1 = src.resolve("mSealed");
        tb.writeJavaFiles(src_m1,
                "module mSealed {}",
                "package pkg1; public sealed class Sealed permits pkg2.Sub{}",
                "package pkg2; public final class Sub extends pkg1.Sealed{}");
        Path classes = base.resolve("classes");
        tb.createDirectories(classes);

        new JavacTask(tb)
                .options("--module-source-path", src.toString())
                .outdir(classes)
                .files(findJavaFiles(src))
                .run()
                .writeAll();
    }

    @Test
    public void testSameModuleSamePkgNeg1(Path base) throws Exception {
        Path src = base.resolve("src");
        Path src_m1 = src.resolve("mSealed");
        // subclass doesn't extend super class
        tb.writeJavaFiles(src_m1,
                "module mSealed {}",
                "package pkg; public sealed class Sealed permits pkg.Sub {}",
                "package pkg; public final class Sub {}");
        Path classes = base.resolve("classes");
        tb.createDirectories(classes);

        List<String> error = new JavacTask(tb)
                .options("-XDrawDiagnostics", "--module-source-path",
                        src.toString())
                .outdir(classes)
                .files(findJavaFiles(src))
                .run(Task.Expect.FAIL)
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        List<String> expected = List.of(
                "Sealed.java:1:52: compiler.err.invalid.permits.clause: (compiler.misc.doesnt.extend.sealed: pkg.Sub)",
                "1 error");
        if (!error.containsAll(expected)) {
            throw new AssertionError("Expected output not found. Found: " + error);
        }
    }

    @Test
    public void testSameModuleSamePkgNeg2(Path base) throws Exception {
        Path src = base.resolve("src");
        Path src_m1 = src.resolve("mSealed");
        // subclass doesn't extend super class
        tb.writeJavaFiles(src_m1,
                "module mSealed {}",
                "package pkg; public sealed interface Sealed permits pkg.Sub1, pkg.Sub2 {}",
                "package pkg; public sealed class Sub1 implements Sealed permits Sub2 {}",
                "package pkg; public final class Sub2 extends Sub1 {}");
        Path classes = base.resolve("classes");
        tb.createDirectories(classes);

        List<String> error = new JavacTask(tb)
                .options("-XDrawDiagnostics", "--module-source-path",
                        src.toString())
                .outdir(classes)
                .files(findJavaFiles(src))
                .run(Task.Expect.FAIL)
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        List<String> expected = List.of(
                "Sealed.java:1:66: compiler.err.invalid.permits.clause: (compiler.misc.doesnt.extend.sealed: pkg.Sub2)",
                "1 error");
        if (!error.containsAll(expected)) {
            throw new AssertionError("Expected output not found. Found: " + error);
        }
    }

    @Test
    public void testDifferentModuleNeg(Path base) throws Exception {
        // check that a subclass in one module can't extend a sealed class in another module
        Path src = base.resolve("src");
        Path src_m1 = src.resolve("mSealed");
        tb.writeJavaFiles(src_m1,
                "module mSealed { exports a; }",
                "package a; public sealed class Base permits b.Impl {}"
        );

        Path src_m2 = src.resolve("mSub");
        tb.writeJavaFiles(src_m2,
                "module mSub { exports b; requires mSealed; }",
                "package b; public final class Impl extends a.Base {}"
        );

        Path classes = base.resolve("classes");
        tb.createDirectories(classes);


        List<String> error =
            new JavacTask(tb)
                .options("-XDrawDiagnostics",
                        "--module-source-path", src.toString(),
                        "--add-reads", "mSealed=mSub")
                .outdir(classes)
                .files(findJavaFiles(src))
                .run(Task.Expect.FAIL)
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        List<String> expected = List.of(
            "Base.java:1:46: compiler.err.class.in.module.cant.extend.sealed.in.diff.module: a.Base, mSealed",
            "1 error"
        );
        if (!error.containsAll(expected)) {
            throw new AssertionError("Expected output not found. Found: " + error);
        }
    }

    @Test
    public void testSeparateCompilation(Path base) throws Exception {
        Path src = base.resolve("src");
        Path src_m = src.resolve("m");
        tb.writeJavaFiles(src_m,
                "module m {}",
                "package pkg.a; public sealed interface Sealed permits pkg.b.Sub {}",
                "package pkg.b; public final class Sub implements pkg.a.Sealed {}");
        Path classes = base.resolve("classes");
        tb.createDirectories(classes);

        new JavacTask(tb)
                .options("-XDrawDiagnostics", "--module-source-path",
                        src.toString())
                .outdir(classes)
                .files(findJavaFiles(src_m))
                .run()
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        new JavacTask(tb)
                .options("-XDrawDiagnostics", "--module-source-path",
                        src.toString(), "-doe")
                .outdir(classes)
                .files(findJavaFiles(src_m.resolve("pkg").resolve("a")))
                .run()
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        new JavacTask(tb)
                .options("-XDrawDiagnostics", "--module-source-path",
                        src.toString(), "-doe")
                .outdir(classes)
                .files(findJavaFiles(src_m.resolve("pkg").resolve("b")))
                .run()
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        tb.cleanDirectory(classes);

        //implicit compilations:
        new JavacTask(tb)
                .options("-XDrawDiagnostics", "--module-source-path",
                        src.toString(), "-doe")
                .outdir(classes)
                .files(findJavaFiles(src_m.resolve("pkg").resolve("a")))
                .run()
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);

        tb.cleanDirectory(classes);

        new JavacTask(tb)
                .options("-XDrawDiagnostics", "--module-source-path",
                        src.toString(), "-doe")
                .outdir(classes)
                .files(findJavaFiles(src_m.resolve("pkg").resolve("b")))
                .run()
                .writeAll()
                .getOutputLines(OutputKind.DIRECT);
    }

    @Test //JDK-8293348
    public void testSupertypePermitsLoop(Path base) throws Exception {
        Path src = base.resolve("src");

        tb.writeJavaFiles(src,
                          "class Main implements T2 {}",
                          "non-sealed interface T2 extends T {}",
                          "sealed interface T permits T2 {}");

        Path out = base.resolve("out");

        Files.createDirectories(out);

        new JavacTask(tb)
                .outdir(out)
                .files(findJavaFiles(src))
                .run()
                .writeAll();

        Files.delete(out.resolve("Main.class"));
        Files.delete(out.resolve("T.class"));

        new JavacTask(tb)
                .outdir(out)
                .options("-cp", out.toString(),
                         "-sourcepath", src.toString())
                .files(src.resolve("Main.java"))
                .run()
                .writeAll();
    }

    @Test
    public void testClientSwapsPermittedSubclassesOrder(Path base) throws Exception {
        Path src = base.resolve("src");
        Path foo = src.resolve("Foo.java");
        Path fooUser = src.resolve("FooUser.java");

        tb.writeFile(foo,
                """
                public sealed interface Foo {
                    record R1() implements Foo {}
                    record R2() implements Foo {}
                }
                """);

        tb.writeFile(fooUser,
                """
                public class FooUser {
                    // see that the order of arguments differ from the order of subclasses of Foo in the source above
                    // we need to check that the order of permitted subclasses of Foo in the class file corresponds to the
                    // original order in the source code
                    public void blah(Foo.R2 a, Foo.R1 b) {}
                }
                """);

        Path out = base.resolve("out");
        Files.createDirectories(out);

        new JavacTask(tb)
                .outdir(out)
                .files(fooUser, foo)
                .run();
        checkSealedClassFile(out, "Foo.class", List.of("Foo$R1", "Foo$R2"));
    }
}
