001/*
002 * Copyright (C) 2022 Ashley Scopes
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *    http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package io.github.ascopes.jct.workspaces;
017
018import io.github.ascopes.jct.workspaces.impl.AbstractManagedDirectory;
019import io.github.ascopes.jct.workspaces.impl.RamDirectoryImpl;
020import io.github.ascopes.jct.workspaces.impl.TempDirectoryImpl;
021import java.io.File;
022import java.nio.file.Path;
023import java.util.function.Function;
024import javax.annotation.processing.Filer;
025
026/**
027 * Strategy to use for creating new test directories.
028 *
029 * <p>This is used to define whether to use a totally isolated in-memory file system,
030 * or whether to use temporary directories on the default file system.
031 *
032 * @author Ashley Scopes
033 * @since 0.0.1
034 */
035public enum PathStrategy {
036  /**
037   * Use RAM-based directories for any created directories.
038   *
039   * <p>This is faster as everything remains in-memory. It also prevents the risk of resources
040   * not being tidied up correctly if the JVM is suddenly shut down. Test directories are also kept
041   * isolated from other tests that may be running in parallel, and isolated from the host operating
042   * system.
043   *
044   * <p>If any annotation processors rely on being run in the {@link File default file system}
045   * rather than using {@link Path the NIO path API} or {@link Filer filers} directly, then they
046   * will not be compatible with reading files from this implementation of test directory. In this
047   * situation, users should opt to use {@link #TEMP_DIRECTORIES} instead.
048   *
049   * <p>Some non-Javac compiler implementations (such as ECJ) may also have some difficulties
050   * dealing with these paths.
051   */
052  RAM_DIRECTORIES(RamDirectoryImpl::newRamDirectory),
053
054  /**
055   * Use OS-level temporary directories for any created directories.
056   *
057   * <p>This will write files to the OS temporary directory. These files will be deleted once the
058   * owning workspace is closed, but may be missed if the JVM is forcefully terminated or crashes.
059   *
060   * <p>There are fewer guarantees of speed and isolation compared to using
061   * {@link #RAM_DIRECTORIES}. However, you do gain the ability to set a breakpoint and inspect the
062   * contents of the directory in a file explorer.
063   *
064   * <p>Since the temporary directories are usually created on the
065   * {@link File default file system}, they are compatible with any annotation processors or
066   * compiler implementations that expect to be run on the default file system only.
067   *
068   * <p>Some restrictions regarding file naming may be present depending on the platform that
069   * is in use, such as file name lengths on Windows. See your system documentation for more
070   * details.
071   */
072  TEMP_DIRECTORIES(TempDirectoryImpl::newTempDirectory);
073
074  @SuppressWarnings("ImmutableEnumChecker")
075  private final Function<String, AbstractManagedDirectory> constructor;
076
077  PathStrategy(Function<String, AbstractManagedDirectory> constructor) {
078    this.constructor = constructor;
079  }
080
081  /**
082   * Create a new instance of the test directory type with the given name.
083   *
084   * <p>Note that calling this directly will return an object that you will have to manually
085   * manage the lifetime for. Failing to do so will result in resources being leaked.
086   *
087   * <p><strong>Users should not call this method by default unless they know what they are
088   * doing.</strong> As a result of this constraint, this method is not part of the public API and
089   * may be subject to change without notice.
090   *
091   * @param name the name to use.
092   * @return the new test directory.
093   */
094  public ManagedDirectory newInstance(String name) {
095    return constructor.apply(name);
096  }
097
098  /**
099   * Determine the default strategy to fall back onto.
100   *
101   * <p>This will be {@link #RAM_DIRECTORIES} by default, but this may be subject to change between
102   * minor versions without notice. Do not rely on this if you are testing code that may be
103   * sensitive to the type of file system being used.
104   *
105   * @return the path strategy to use by default.
106   */
107  public static PathStrategy defaultStrategy() {
108    return RAM_DIRECTORIES;
109  }
110}