1 // ******************************************************************************
2 //
3 // Title: Force Field X.
4 // Description: Force Field X - Software for Molecular Biophysics.
5 // Copyright: Copyright (c) Michael J. Schnieders 2001-2025.
6 //
7 // This file is part of Force Field X.
8 //
9 // Force Field X is free software; you can redistribute it and/or modify it
10 // under the terms of the GNU General Public License version 3 as published by
11 // the Free Software Foundation.
12 //
13 // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 // details.
17 //
18 // You should have received a copy of the GNU General Public License along with
19 // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20 // Place, Suite 330, Boston, MA 02111-1307 USA
21 //
22 // Linking this library statically or dynamically with other modules is making a
23 // combined work based on this library. Thus, the terms and conditions of the
24 // GNU General Public License cover the whole combination.
25 //
26 // As a special exception, the copyright holders of this library give you
27 // permission to link this library with independent modules to produce an
28 // executable, regardless of the license terms of these independent modules, and
29 // to copy and distribute the resulting executable under terms of your choice,
30 // provided that you also meet, for each linked independent module, the terms
31 // and conditions of the license of that module. An independent module is a
32 // module which is not derived from or based on this library. If you modify this
33 // library, you may extend this exception to your version of the library, but
34 // you are not obligated to do so. If you do not wish to do so, delete this
35 // exception statement from your version.
36 //
37 // ******************************************************************************
38 package ffx.utilities;
39
40 import static java.lang.String.format;
41 import static org.junit.Assert.fail;
42
43 import java.io.IOException;
44 import java.nio.file.Files;
45 import java.nio.file.Path;
46 import java.util.Properties;
47 import java.util.logging.Level;
48 import java.util.logging.Logger;
49 import org.junit.After;
50 import org.junit.AfterClass;
51 import org.junit.Before;
52 import org.junit.BeforeClass;
53
54 /**
55 * The FFXTest configures the context for FFX tests. This includes: 1) Sets testing related
56 * environment variables:
57 * <br>
58 * Set "-Dffx.ci=true" for a CI environment (default: false).
59 * <br>
60 * Set "-Dffx.openMM=true" for CUDA dependent OpenMM tests (default: false).
61 * <br>
62 * 2) Configures the logging level, using the ffx.test.log System property (default: INFO).
63 * <br>
64 * 3) Stores System properties prior to each test, and restores them after each test (i.e. properties
65 * set by a test do not affect the next test).
66 * <br>
67 * 4) Upon request, creates a temporary that is deleted after the current test is completed.
68 * <br>
69 * 5) Requests garbage collection after each test.
70 *
71 * @author Michael J. Schnieders
72 */
73 public abstract class FFXTest {
74
75 /** Constant <code>ffxCI=System.getProperty("ffx.ci", "false").equalsIgnoreCase("true")</code> */
76 public static final boolean ffxCI =
77 System.getProperty("ffx.ci", "false").equalsIgnoreCase("true");
78
79 /**
80 * Constant <code>ffxOpenMM=System.getProperty("ffx.openMM", "false").equalsIgnoreCase("true")
81 * </code>
82 */
83 public static final boolean ffxOpenMM =
84 System.getProperty("ffx.openMM", "false").equalsIgnoreCase("true");
85
86 /** Constant <code>logger</code> */
87 protected static final Logger logger = Logger.getLogger(FFXTest.class.getName());
88
89 private static final Level origLevel;
90 private static final Level testLevel;
91 private static Properties properties;
92 private Path path = null;
93
94 static {
95 Level level;
96 try {
97 level = Level.parse(System.getProperty("ffx.log", "INFO").toUpperCase());
98 } catch (Exception ex) {
99 logger.warning(format(" Exception %s in parsing value of ffx.log", ex));
100 level = Level.INFO;
101 }
102 origLevel = level;
103 try {
104 level = Level.parse(System.getProperty("ffx.test.log", "WARNING").toUpperCase());
105 } catch (Exception ex) {
106 logger.warning(format(" Exception %s in parsing value of ffx.test.log", ex));
107 }
108 testLevel = level;
109 System.setProperty("ffx.log", testLevel.toString());
110 }
111
112 /**
113 * FFXTest constructor.
114 */
115 public FFXTest() {
116 // Empty constructor.
117 }
118
119 /**
120 * afterClass.
121 */
122 @AfterClass
123 public static void afterClass() {
124 Logger.getGlobal().setLevel(origLevel);
125 Logger.getLogger("ffx").setLevel(origLevel);
126 logger.setLevel(origLevel);
127 }
128
129 /**
130 * beforeClass.
131 */
132 @BeforeClass
133 public static void beforeClass() {
134 // Set appropriate logging levels for interior/exterior Loggers.
135 Logger.getGlobal().setLevel(testLevel);
136 Logger.getLogger("ffx").setLevel(testLevel);
137 logger.setLevel(testLevel);
138 }
139
140 /**
141 * Create temporary testing directory that will be deleted after the current test.
142 *
143 * @return Path to the testing directory.
144 */
145 public Path registerTemporaryDirectory() {
146 deleteTemporaryDirectory();
147 try {
148 path = Files.createTempDirectory("FFXTestDirectory");
149 } catch (java.io.IOException e) {
150 fail(" Could not create a temporary directory.");
151 }
152 return path;
153 }
154
155 /**
156 * Delete the temporary test directory.
157 */
158 private void deleteTemporaryDirectory() {
159 // Delete the test directory if it exists.
160 if (path != null) {
161 try {
162 DirectoryUtils.deleteDirectoryTree(path);
163 } catch (IOException e) {
164 System.out.println(e.getMessage());
165 fail(" Exception deleting files created by Frac2Cart.");
166 }
167 path = null;
168 }
169 }
170
171 /**
172 * afterTest.
173 */
174 @After
175 public void afterTest() {
176 // All properties are set to the values they were at the beginning of the test.
177 System.setProperties(properties);
178
179 // Delete the test directory if it exists.
180 deleteTemporaryDirectory();
181
182 // Collect garbage.
183 System.gc();
184 }
185
186 /**
187 * beforeTest.
188 */
189 @Before
190 public void beforeTest() {
191 // New properties object that will hold the property key-value pairs that were present
192 // at the beginning of the test.
193 properties = new Properties();
194
195 // currentProperties holds the properties at the beginning of the test.
196 Properties currentProperties = System.getProperties();
197
198 // All key-value pairs from currentProperties are stored in the properties object.
199 currentProperties.stringPropertyNames()
200 .forEach(key -> properties.setProperty(key, currentProperties.getProperty(key)));
201 }
202 }