1 package com.pty4j;
2 
3 import com.google.common.base.Function;
4 import com.pty4j.util.PtyUtil;
5 import com.sun.jna.Platform;
6 import com.sun.jna.platform.win32.Kernel32;
7 import jtermios.JTermios;
8 import org.apache.log4j.Logger;
9 import org.jetbrains.annotations.NotNull;
10 import org.jetbrains.annotations.Nullable;
11 
12 import java.io.File;
13 import java.net.MalformedURLException;
14 import java.net.URISyntaxException;
15 import java.net.URL;
16 import java.nio.file.Path;
17 import java.nio.file.Paths;
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.List;
21 import java.util.Objects;
22 import java.util.regex.Pattern;
23 import java.util.stream.Collectors;
24 
25 /**
26  * @author traff
27  */
28 public class TestUtil {
29 
getTestDataPath()30   public static @NotNull String getTestDataPath() {
31     return Paths.get("test/testData").toAbsolutePath().normalize().toString();
32   }
33 
34   @NotNull
getJavaCommand(@otNull Class<?> aClass, String... args)35   public static String[] getJavaCommand(@NotNull Class<?> aClass, String... args) {
36     List<String> result = new ArrayList<>();
37     result.add(getJavaExecutablePath());
38     result.add("-cp");
39     result.add(getJarPathForClasses(aClass, WinSize.class, Logger.class, JTermios.class, Platform.class,
40             Kernel32.class, Function.class));
41     result.add(aClass.getName());
42     result.addAll(Arrays.asList(args));
43     return result.toArray(new String[0]);
44   }
45 
46   @NotNull
getJavaExecutablePath()47   private static String getJavaExecutablePath() {
48     return System.getProperty("java.home") + File.separator + "bin"
49         + File.separator + (Platform.isWindows() ? "java.exe" : "java");
50   }
51 
52   /**
53    * Copied from com.intellij.openapi.application.PathManager#getJarPathForClass.
54    */
55   @NotNull
getJarPathForClass(@otNull Class<?> aClass)56   private static String getJarPathForClass(@NotNull Class<?> aClass) {
57     String resourceRoot = getResourceRoot(aClass, "/" + aClass.getName().replace('.', '/') + ".class");
58     return new File(Objects.requireNonNull(resourceRoot)).getAbsolutePath();
59   }
60 
getJarPathForClasses(@otNull Class<?>.... classes)61   private static String getJarPathForClasses(@NotNull Class<?>... classes) {
62     List<String> paths = Arrays.stream(classes).map(TestUtil::getJarPathForClass).collect(Collectors.toList());
63     return String.join(Platform.isWindows() ? ";" : ":", paths);
64   }
65 
66   @Nullable
getResourceRoot(@otNull Class<?> context, @NotNull String path)67   private static String getResourceRoot(@NotNull Class<?> context, @NotNull String path) {
68     URL url = context.getResource(path);
69     if (url == null) {
70       url = ClassLoader.getSystemResource(path.substring(1));
71     }
72     return url != null ? extractRoot(url, path) : null;
73   }
74 
75   @NotNull
extractRoot(@otNull URL resourceURL, @NotNull String resourcePath)76   private static String extractRoot(@NotNull URL resourceURL, @NotNull String resourcePath) {
77     if (!resourcePath.startsWith("/") && !resourcePath.startsWith("\\")) {
78       throw new IllegalStateException("precondition failed: " + resourcePath);
79     }
80 
81     String resultPath = null;
82     String protocol = resourceURL.getProtocol();
83     if ("file".equals(protocol)) {
84       String path = urlToFile(resourceURL).getPath();
85       String testPath = path.replace('\\', '/');
86       String testResourcePath = resourcePath.replace('\\', '/');
87       if (testPath.endsWith(testResourcePath)) {
88         resultPath = path.substring(0, path.length() - resourcePath.length());
89       }
90     }
91     else if ("jar".equals(protocol)) {
92       resultPath = getJarPath(resourceURL.getFile());
93     }
94 
95     if (resultPath == null) {
96       throw new IllegalStateException("Cannot extract '" + resourcePath + "' from '" + resourceURL + "', " + protocol);
97     }
98     return resultPath;
99   }
100 
101   @NotNull
urlToFile(@otNull URL url)102   private static File urlToFile(@NotNull URL url) {
103     try {
104       return new File(url.toURI().getSchemeSpecificPart());
105     }
106     catch (URISyntaxException e) {
107       throw new IllegalArgumentException("URL='" + url.toString() + "'", e);
108     }
109   }
110 
getJarPath(@otNull String urlFilePart)111   private static @Nullable String getJarPath(@NotNull String urlFilePart) {
112     int pivot = urlFilePart.indexOf("!/");
113     if (pivot < 0) {
114       return null;
115     }
116     String fileUrlStr = urlFilePart.substring(0, pivot);
117 
118     String filePrefix = "file:";
119     if (!fileUrlStr.startsWith(filePrefix)) {
120       return fileUrlStr;
121     }
122 
123     URL fileUrl;
124     try {
125       fileUrl = new URL(fileUrlStr);
126     }
127     catch (MalformedURLException e) {
128       return null;
129     }
130 
131     File result = urlToFile(fileUrl);
132     return result.getPath().replace('\\', '/');
133   }
134 
135   @NotNull
getBuiltNativeFolder()136   public static Path getBuiltNativeFolder() {
137     return Paths.get("os").toAbsolutePath().normalize();
138   }
139 
setLocalPtyLib()140   public static void setLocalPtyLib() {
141     if ("false".equals(System.getProperty(PtyUtil.PREFERRED_NATIVE_FOLDER_KEY))) {
142       System.clearProperty(PtyUtil.PREFERRED_NATIVE_FOLDER_KEY);
143     }
144     else {
145       System.setProperty(PtyUtil.PREFERRED_NATIVE_FOLDER_KEY, getBuiltNativeFolder().toString());
146     }
147   }
148 
assertConsoleExists()149   public static void assertConsoleExists() {
150     if (System.console() == null) {
151       System.err.println("Not a terminal");
152       System.exit(1);
153     }
154   }
155 
getTestWaitTimeoutSeconds()156   public static int getTestWaitTimeoutSeconds() {
157     String valueStr = System.getenv("PTY4J_TEST_TIMEOUT_SECONDS");
158     if (valueStr != null) {
159       try {
160         int value = Integer.parseInt(valueStr);
161         if (value > 0) {
162           System.out.println("pty4j test timeout is set to " + value + " seconds");
163           return value;
164         }
165       }
166       catch (NumberFormatException ignored) {
167       }
168     }
169     return 60;
170   }
171 
findInPath(@otNull String fileName)172   public static @Nullable File findInPath(@NotNull String fileName) {
173     String pathValue = System.getenv("PATH");
174     if (pathValue == null) {
175       return null;
176     }
177     List<String> dirPaths = getPathDirs(pathValue);
178     for (String dirPath : dirPaths) {
179       File dir = new File(dirPath);
180       if (dir.isAbsolute() && dir.isDirectory()) {
181         File exeFile = new File(dir, fileName);
182         if (exeFile.isFile() && exeFile.canExecute()) {
183           return exeFile;
184         }
185       }
186     }
187     return null;
188   }
189 
getPathDirs(@otNull String pathEnvVarValue)190   private static @NotNull List<String> getPathDirs(@NotNull String pathEnvVarValue) {
191     return Arrays.asList(pathEnvVarValue.split(Pattern.quote(File.pathSeparator)));
192   }
193 }
194