001/* 002 * Copyright (C) 2022 - 2024, the original author or authors. 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; 025import org.apiguardian.api.API; 026import org.apiguardian.api.API.Status; 027 028/** 029 * Strategy to use for creating new test directories. 030 * 031 * <p>This is used to define whether to use a totally isolated in-memory file system, 032 * or whether to use temporary directories on the default file system. 033 * 034 * @author Ashley Scopes 035 * @since 0.0.1 036 */ 037@API(since = "0.0.1", status = Status.STABLE) 038public enum PathStrategy { 039 /** 040 * Use RAM-based directories for any created directories. 041 * 042 * <p>This is faster as everything remains in-memory. It also prevents the risk of resources 043 * not being tidied up correctly if the JVM is suddenly shut down. Test directories are also kept 044 * isolated from other tests that may be running in parallel, and isolated from the host operating 045 * system. 046 * 047 * <p>If any annotation processors rely on being run in the {@link File default file system} 048 * rather than using {@link Path the NIO path API} or {@link Filer filers} directly, then they 049 * will not be compatible with reading files from this implementation of test directory. In this 050 * situation, users should opt to use {@link #TEMP_DIRECTORIES} instead. 051 * 052 * <p>Some non-Javac compiler implementations (such as ECJ) may also have some difficulties 053 * dealing with these paths. 054 */ 055 RAM_DIRECTORIES(RamDirectoryImpl::newRamDirectory), 056 057 /** 058 * Use OS-level temporary directories for any created directories. 059 * 060 * <p>This will write files to the OS temporary directory. These files will be deleted once the 061 * owning workspace is closed, but may be missed if the JVM is forcefully terminated or crashes. 062 * 063 * <p>There are fewer guarantees of speed and isolation compared to using 064 * {@link #RAM_DIRECTORIES}. However, you do gain the ability to set a breakpoint and inspect the 065 * contents of the directory in a file explorer. 066 * 067 * <p>Since the temporary directories are usually created on the 068 * {@link File default file system}, they are compatible with any annotation processors or 069 * compiler implementations that expect to be run on the default file system only. 070 * 071 * <p>Some restrictions regarding file naming may be present depending on the platform that 072 * is in use, such as file name lengths on Windows. See your system documentation for more 073 * details. 074 */ 075 TEMP_DIRECTORIES(TempDirectoryImpl::newTempDirectory); 076 077 private final Function<String, AbstractManagedDirectory> constructor; 078 079 PathStrategy(Function<String, AbstractManagedDirectory> constructor) { 080 this.constructor = constructor; 081 } 082 083 /** 084 * Create a new instance of the test directory type with the given name. 085 * 086 * <p>Note that calling this directly will return an object that you will have to manually 087 * manage the lifetime for. Failing to do so will result in resources being leaked. 088 * 089 * <p><strong>Users should not call this method by default unless they know what they are 090 * doing.</strong> As a result of this constraint, this method is not part of the public API and 091 * may be subject to change without notice. 092 * 093 * @param name the name to use. 094 * @return the new test directory. 095 */ 096 @API(since = "0.0.1", status = Status.INTERNAL) 097 public ManagedDirectory newInstance(String name) { 098 return constructor.apply(name); 099 } 100 101 /** 102 * Determine the default strategy to fall back onto. 103 * 104 * <p>This will be {@link #RAM_DIRECTORIES} by default, but this may be subject to change between 105 * minor versions without notice, so do not rely on this if you are testing code that may be 106 * sensitive to the type of file system being used. 107 * 108 * @return the path strategy to use by default. 109 */ 110 public static PathStrategy defaultStrategy() { 111 return RAM_DIRECTORIES; 112 } 113}