/*
 * Copyright (c) 2023, 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
 * @bug 8114830
 * @summary Verify FileAlreadyExistsException is not thrown for REPLACE_EXISTING
 * @library ..
 * @build CopyInterference
 * @run junit CopyInterference
 */
import java.io.InputStream;
import java.io.IOException;
import java.nio.file.CopyOption;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.FileSystemException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

import static java.nio.file.StandardCopyOption.*;
import static java.nio.file.LinkOption.*;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

public class CopyInterference {

    private static final int N_THREADS = 2;

    private static final AtomicBoolean running = new AtomicBoolean(true);

    private static class CopyTask implements Runnable {
        final Path source;
        final Path target;
        final CopyOption[] options;

        CopyTask(Path source, Path target, CopyOption[] options) {
            this.source = source;
            this.target = target;
            this.options = options;
        }

        @Override
        public void run() {
            try {
                while (running.get()) {
                    Files.copy(source, target, options);
                }
            } catch (FileAlreadyExistsException e) {
                throw new RuntimeException("Unexpected exception", e);
            } catch (FileSystemException e) {
                System.out.printf("Expected FileSystemException: \"%s\"%n",
                                  e.getMessage());
            } catch (IOException e) {
                throw new RuntimeException("Unexpected exception", e);
            } finally {
                running.set(false);
            }
        }
    }

    private static Stream<Arguments> pathAndOptionsProvider()
        throws IOException {
        Path parent = Path.of(System.getProperty("test.dir", "."));
        Path dir = Files.createTempDirectory(parent, "foobargus");

        List<Arguments> list = new ArrayList<Arguments>();

        // regular file
        Path sourceFile = Files.createTempFile(dir, "foo", "baz");
        Class c = CopyInterference.class;
        String name = "CopyInterference.class";

        try (InputStream in = c.getResourceAsStream(name)) {
            Files.copy(in, sourceFile, REPLACE_EXISTING);
        }

        Arguments args = Arguments.of(sourceFile, dir.resolve("targetFile"),
                                      new CopyOption[] {REPLACE_EXISTING});
        list.add(args);

        // directory
        Path sourceDirectory = Files.createTempDirectory(dir, "fubar");
        args = Arguments.of(sourceDirectory, dir.resolve("targetDir"),
                            new CopyOption[] {REPLACE_EXISTING});
        list.add(args);

        if (TestUtil.supportsSymbolicLinks(dir)) {
            // symbolic link, followed
            Path link = dir.resolve("link");
            Files.createSymbolicLink(link, sourceFile);
            args = Arguments.of(link, dir.resolve("linkFollowed"),
                                new CopyOption[] {REPLACE_EXISTING});
            list.add(args);

            // symbolic link, not followed
            args = Arguments.of(link, dir.resolve("linkNotFollowed"),
                                new CopyOption[] {REPLACE_EXISTING,
                                                  NOFOLLOW_LINKS});
            list.add(args);
        } else {
            System.out.println("Links not supported: not testing links");
        }

        return list.stream();
    }

    @ParameterizedTest
    @MethodSource("pathAndOptionsProvider")
    void copy(Path source, Path target, CopyOption[] options)
        throws InterruptedException, IOException {

        Future<?>[] results = new Future<?>[N_THREADS];
        try (ExecutorService es = Executors.newFixedThreadPool(N_THREADS)) {
            CopyTask copyTask = new CopyTask(source, target, options);
            for (int i = 0; i < N_THREADS; i++)
                results[i] = es.submit(copyTask);
        }

        for (Future<?> res : results) {
            try {
                res.get();
            } catch (ExecutionException e) {
                throw new RuntimeException(res.exceptionNow());
            }
        }
    }
}
