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; 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 private final Function<String, AbstractManagedDirectory> constructor; 075 076 PathStrategy(Function<String, AbstractManagedDirectory> constructor) { 077 this.constructor = constructor; 078 } 079 080 /** 081 * Create a new instance of the test directory type with the given name. 082 * 083 * <p>Note that calling this directly will return an object that you will have to manually 084 * manage the lifetime for. Failing to do so will result in resources being leaked. 085 * 086 * <p><strong>Users should not call this method by default unless they know what they are 087 * doing.</strong> As a result of this constraint, this method is not part of the public API and 088 * may be subject to change without notice. 089 * 090 * @param name the name to use. 091 * @return the new test directory. 092 */ 093 public ManagedDirectory newInstance(String name) { 094 return constructor.apply(name); 095 } 096 097 /** 098 * Determine the default strategy to fall back onto. 099 * 100 * <p>This will be {@link #RAM_DIRECTORIES} by default, but this may be subject to change between 101 * minor versions without notice, so do not rely on this if you are testing code that may be 102 * sensitive to the type of file system being used. 103 * 104 * @return the path strategy to use by default. 105 */ 106 public static PathStrategy defaultStrategy() { 107 return RAM_DIRECTORIES; 108 } 109}