mirror of
https://github.com/alibaba/testable-mock.git
synced 2025-01-25 11:51:15 +08:00
always generate log file
This commit is contained in:
parent
93cdef1d6c
commit
01e9890234
@ -3,7 +3,7 @@ package com.alibaba.demo.java2kotlin
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
object PathUtil {
|
object PathDemo {
|
||||||
|
|
||||||
fun deleteRecursively(file: File) {
|
fun deleteRecursively(file: File) {
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
@ -5,7 +5,7 @@ import com.alibaba.testable.core.matcher.InvokeVerifier.verify
|
|||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class PathUtilTest {
|
class PathDemoTest {
|
||||||
|
|
||||||
class Mock {
|
class Mock {
|
||||||
@MockMethod
|
@MockMethod
|
||||||
@ -42,7 +42,7 @@ class PathUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun should_mock_java_method_invoke_in_kotlin() {
|
fun should_mock_java_method_invoke_in_kotlin() {
|
||||||
PathUtil.deleteRecursively(File("/a/b/"))
|
PathDemo.deleteRecursively(File("/a/b/"))
|
||||||
verify("listFiles").withTimes(2)
|
verify("listFiles").withTimes(2)
|
||||||
verify("delete").withTimes(4)
|
verify("delete").withTimes(4)
|
||||||
}
|
}
|
@ -3,6 +3,7 @@ package com.alibaba.testable.agent;
|
|||||||
import com.alibaba.testable.agent.transformer.TestableClassTransformer;
|
import com.alibaba.testable.agent.transformer.TestableClassTransformer;
|
||||||
import com.alibaba.testable.agent.util.GlobalConfig;
|
import com.alibaba.testable.agent.util.GlobalConfig;
|
||||||
import com.alibaba.testable.core.model.MockScope;
|
import com.alibaba.testable.core.model.MockScope;
|
||||||
|
import com.alibaba.testable.core.util.LogUtil;
|
||||||
import com.alibaba.ttl.threadpool.agent.TtlAgent;
|
import com.alibaba.ttl.threadpool.agent.TtlAgent;
|
||||||
|
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
@ -23,6 +24,7 @@ public class PreMain {
|
|||||||
private static boolean enhanceThreadLocal = false;
|
private static boolean enhanceThreadLocal = false;
|
||||||
|
|
||||||
public static void premain(String agentArgs, Instrumentation inst) {
|
public static void premain(String agentArgs, Instrumentation inst) {
|
||||||
|
GlobalConfig.setupLogRootPath();
|
||||||
parseArgs(agentArgs);
|
parseArgs(agentArgs);
|
||||||
if (enhanceThreadLocal) {
|
if (enhanceThreadLocal) {
|
||||||
// add transmittable thread local transformer
|
// add transmittable thread local transformer
|
||||||
@ -30,6 +32,7 @@ public class PreMain {
|
|||||||
}
|
}
|
||||||
// add testable mock transformer
|
// add testable mock transformer
|
||||||
inst.addTransformer(new TestableClassTransformer());
|
inst.addTransformer(new TestableClassTransformer());
|
||||||
|
cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void parseArgs(String args) {
|
private static void parseArgs(String args) {
|
||||||
@ -60,4 +63,13 @@ public class PreMain {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void cleanup() {
|
||||||
|
Runtime.getRuntime().addShutdownHook(new Thread() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
LogUtil.cleanup();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -211,7 +211,7 @@ public class BytecodeUtil {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
String dumpFile = StringUtil.joinPath(dumpPath,
|
String dumpFile = PathUtil.join(dumpPath,
|
||||||
className.replace(SLASH, DOT).replace(DOLLAR, UNDERLINE) + ".class");
|
className.replace(SLASH, DOT).replace(DOLLAR, UNDERLINE) + ".class");
|
||||||
LogUtil.verbose("Dump class: " + dumpFile);
|
LogUtil.verbose("Dump class: " + dumpFile);
|
||||||
FileOutputStream stream = new FileOutputStream(dumpFile);
|
FileOutputStream stream = new FileOutputStream(dumpFile);
|
||||||
|
@ -14,6 +14,7 @@ public class GlobalConfig {
|
|||||||
private static final String MUTE = "mute";
|
private static final String MUTE = "mute";
|
||||||
private static final String DEBUG = "debug";
|
private static final String DEBUG = "debug";
|
||||||
private static final String VERBOSE = "verbose";
|
private static final String VERBOSE = "verbose";
|
||||||
|
private static final String USER_DIR = "user.dir";
|
||||||
|
|
||||||
private static String dumpPath = null;
|
private static String dumpPath = null;
|
||||||
private static String pkgPrefix = null;
|
private static String pkgPrefix = null;
|
||||||
@ -56,4 +57,9 @@ public class GlobalConfig {
|
|||||||
public static void setDefaultMockScope(MockScope scope) {
|
public static void setDefaultMockScope(MockScope scope) {
|
||||||
defaultMockScope = scope;
|
defaultMockScope = scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setupLogRootPath() {
|
||||||
|
LogUtil.setGlobalLogPath(
|
||||||
|
PathUtil.getFirstLevelFolder(System.getProperty(USER_DIR), Object.class.getResource("/").getPath()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.alibaba.testable.agent.util;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class PathUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Join a path text and a file name to full file path
|
||||||
|
* @param folder path text
|
||||||
|
* @param file file name
|
||||||
|
* @return joined full file path
|
||||||
|
*/
|
||||||
|
public static String join(String folder, String file) {
|
||||||
|
return (folder.endsWith(File.separator) ? folder : (folder + File.separator)) + file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the absolute path of the first sub-folder from root folder to target path
|
||||||
|
* @param rootFolder specify root folder path
|
||||||
|
* @param targetPath any sub path inside root folder
|
||||||
|
* @return first sub-folder path
|
||||||
|
*/
|
||||||
|
public static String getFirstLevelFolder(String rootFolder, String targetPath) {
|
||||||
|
if (!targetPath.startsWith(rootFolder) || targetPath.length() <= rootFolder.length() + 1) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
char separator = targetPath.charAt(rootFolder.length());
|
||||||
|
int pos = targetPath.indexOf(separator, rootFolder.length() + 1);
|
||||||
|
return pos > 0 ? targetPath.substring(0, pos) : "";
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,5 @@
|
|||||||
package com.alibaba.testable.agent.util;
|
package com.alibaba.testable.agent.util;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author flin
|
* @author flin
|
||||||
*/
|
*/
|
||||||
@ -21,14 +19,4 @@ public class StringUtil {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* join a path text and a file name to full file path
|
|
||||||
* @param folder path text
|
|
||||||
* @param file file name
|
|
||||||
* @return joined full file path
|
|
||||||
*/
|
|
||||||
public static String joinPath(String folder, String file) {
|
|
||||||
return (folder.endsWith(File.separator) ? folder : (folder + File.separator)) + file;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.alibaba.testable.agent.util;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class PathUtilTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void should_get_sub_folder() {
|
||||||
|
assertEquals("/ab/cd", PathUtil.getFirstLevelFolder("/ab", "/ab/cd/ef/gh"));
|
||||||
|
assertEquals("c:\\ab\\cd", PathUtil.getFirstLevelFolder("c:\\ab", "c:\\ab\\cd\\ef\\gh"));
|
||||||
|
assertEquals("", PathUtil.getFirstLevelFolder("/ab", "/ab"));
|
||||||
|
assertEquals("", PathUtil.getFirstLevelFolder("/ab/cd", "/ab"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -2,34 +2,55 @@ package com.alibaba.testable.core.util;
|
|||||||
|
|
||||||
import com.alibaba.testable.core.model.LogLevel;
|
import com.alibaba.testable.core.model.LogLevel;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author flin
|
* @author flin
|
||||||
*/
|
*/
|
||||||
public class LogUtil {
|
public class LogUtil {
|
||||||
|
|
||||||
|
private static final String TESTABLE_AGENT_LOG = "testable-agent.log";
|
||||||
|
|
||||||
private static LogLevel defaultLogLevel = LogLevel.DEFAULT;
|
private static LogLevel defaultLogLevel = LogLevel.DEFAULT;
|
||||||
private static LogLevel currentLogLevel = LogLevel.DEFAULT;
|
private static LogLevel currentLogLevel = LogLevel.DEFAULT;
|
||||||
|
private static FileOutputStream logFileStream = null;
|
||||||
|
|
||||||
public static void verbose(String msg, Object... args) {
|
public static void verbose(String msg, Object... args) {
|
||||||
if (isVerboseEnabled()) {
|
if (isVerboseEnabled()) {
|
||||||
System.out.println(String.format("[VERBOSE] " + msg, args));
|
String text = String.format(msg + "\n", args);
|
||||||
|
System.out.print("[VERBOSE] ");
|
||||||
|
System.out.print(text);
|
||||||
|
write("[TIP] ");
|
||||||
|
write(text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void diagnose(String msg, Object... args) {
|
public static void diagnose(String msg, Object... args) {
|
||||||
|
String text = String.format(msg + "\n", args);
|
||||||
if (currentLogLevel.level >= LogLevel.ENABLE.level) {
|
if (currentLogLevel.level >= LogLevel.ENABLE.level) {
|
||||||
System.out.println(String.format("[DIAGNOSE] " + msg, args));
|
System.out.print("[DIAGNOSE] ");
|
||||||
|
System.out.print(text);
|
||||||
}
|
}
|
||||||
|
write("[INFO] ");
|
||||||
|
write(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void warn(String msg, Object... args) {
|
public static void warn(String msg, Object... args) {
|
||||||
|
String text = String.format("[WARN] " + msg + "\n", args);
|
||||||
if (currentLogLevel.level >= LogLevel.DEFAULT.level) {
|
if (currentLogLevel.level >= LogLevel.DEFAULT.level) {
|
||||||
System.err.println(String.format("[WARN] " + msg, args));
|
System.err.print(text);
|
||||||
}
|
}
|
||||||
|
write(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void error(String msg, Object... args) {
|
public static void error(String msg, Object... args) {
|
||||||
System.err.println(String.format("[ERROR] " + msg, args));
|
String text = String.format("[ERROR] " + msg + "\n", args);
|
||||||
|
System.err.print(text);
|
||||||
|
write(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -52,4 +73,38 @@ public class LogUtil {
|
|||||||
currentLogLevel = defaultLogLevel;
|
currentLogLevel = defaultLogLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setGlobalLogPath(String logFolderPath) {
|
||||||
|
if (logFolderPath.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String logFilePath = logFolderPath + File.separator + TESTABLE_AGENT_LOG;
|
||||||
|
try {
|
||||||
|
logFileStream = new FileOutputStream(logFilePath);
|
||||||
|
diagnose("Start at %s", new Date().toString());
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
warn("Failed to create log file %s", logFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cleanup() {
|
||||||
|
try {
|
||||||
|
if (logFileStream != null) {
|
||||||
|
diagnose("Completed at %s", new Date().toString());
|
||||||
|
logFileStream.flush();
|
||||||
|
logFileStream.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
warn("Log file is not closed properly");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void write(String text) {
|
||||||
|
try {
|
||||||
|
if (logFileStream != null) {
|
||||||
|
logFileStream.write(text.getBytes());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user