diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2321b9e..9fa01c4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -4,6 +4,7 @@ on: push: branches: - master + pull_request: workflow_dispatch: inputs: release_version: @@ -54,6 +55,7 @@ jobs: release: needs: ["build-java"] + if: github.event_name != 'pull_request' runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/src/main/java/w/core/compiler/WCompiler.java b/src/main/java/w/core/compiler/WCompiler.java index dcab0f4..369bd8f 100644 --- a/src/main/java/w/core/compiler/WCompiler.java +++ b/src/main/java/w/core/compiler/WCompiler.java @@ -10,6 +10,7 @@ import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import w.Global; +import w.util.IOUtils; import java.io.InputStream; import java.util.ArrayList; @@ -163,7 +164,7 @@ private static List findReferencedNestedClasses(String pureClassName, St if (inputStream == null) { return nested; } - byte[] bytes = inputStream.readAllBytes(); + byte[] bytes = IOUtils.readAllBytes(inputStream); new ClassReader(bytes).accept(new ClassVisitor(Opcodes.ASM9) { @Override public MethodVisitor visitMethod(int access, String name, String descriptor, diff --git a/src/main/java/w/core/model/ChangeResultTransformer.java b/src/main/java/w/core/model/ChangeResultTransformer.java index cae7e49..297b75d 100644 --- a/src/main/java/w/core/model/ChangeResultTransformer.java +++ b/src/main/java/w/core/model/ChangeResultTransformer.java @@ -28,6 +28,7 @@ import org.objectweb.asm.tree.VarInsnNode; import w.Global; import w.core.compiler.WCompiler; +import w.util.IOUtils; import w.core.constant.Codes; import w.web.message.ChangeResultMessage; @@ -244,7 +245,7 @@ private byte[] readClassBytes(ClassLoader loader, String className) { if (inputStream == null) { return null; } - return inputStream.readAllBytes(); + return IOUtils.readAllBytes(inputStream); } catch (Throwable e) { Global.debug("change result read class bytes error: " + className + ", " + e.getMessage()); return null; diff --git a/src/main/java/w/core/model/OuterWatchTransformer.java b/src/main/java/w/core/model/OuterWatchTransformer.java index 282b185..b863e79 100644 --- a/src/main/java/w/core/model/OuterWatchTransformer.java +++ b/src/main/java/w/core/model/OuterWatchTransformer.java @@ -18,6 +18,7 @@ import w.core.asm.WAdviceAdapter; import w.core.diagnostic.DiagnosticRuntime; import w.core.diagnostic.OuterWatchConfig; +import w.util.IOUtils; import w.web.message.OuterWatchMessage; import java.io.InputStream; @@ -227,7 +228,7 @@ private byte[] readClassBytes(ClassLoader loader, String className) { if (inputStream == null) { return null; } - return inputStream.readAllBytes(); + return IOUtils.readAllBytes(inputStream); } catch (Throwable e) { Global.debug("outer watch read class bytes error: " + className + ", " + e.getMessage()); return null; diff --git a/src/main/java/w/util/IOUtils.java b/src/main/java/w/util/IOUtils.java new file mode 100644 index 0000000..02a9388 --- /dev/null +++ b/src/main/java/w/util/IOUtils.java @@ -0,0 +1,20 @@ +package w.util; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public final class IOUtils { + private IOUtils() { + } + + public static byte[] readAllBytes(InputStream inputStream) throws IOException { + ByteArrayOutputStream buffer = new ByteArrayOutputStream(); + byte[] data = new byte[8192]; + int n; + while ((n = inputStream.read(data)) != -1) { + buffer.write(data, 0, n); + } + return buffer.toByteArray(); + } +} diff --git a/src/test/java/w/core/ChangeResultTest.java b/src/test/java/w/core/ChangeResultTest.java index 568c437..7e9550d 100644 --- a/src/test/java/w/core/ChangeResultTest.java +++ b/src/test/java/w/core/ChangeResultTest.java @@ -174,7 +174,7 @@ public void asmShouldFailWhenNoMatchingInnerCall() throws IOException, Interrupt SwapResult result = swapper.swap(msg); Assertions.assertFalse(result.isSuccess()); - Assertions.assertTrue(String.valueOf(result.getMessage()).contains("nothing was enhanced")); + Assertions.assertTrue(String.valueOf(result.getMessage()).contains("noSuchMethod")); } @Test diff --git a/src/test/java/w/core/OuterWatchTest.java b/src/test/java/w/core/OuterWatchTest.java index 9567290..9d4b921 100644 --- a/src/test/java/w/core/OuterWatchTest.java +++ b/src/test/java/w/core/OuterWatchTest.java @@ -329,10 +329,13 @@ public void includeNestedShouldCollectRecursiveLambdaTargets() { Map> targetMethods = transformer.getTargetMethods(); Set methods = targetMethods.get("w.core.ChangeTarget"); - long nestedLambdaCount = methods.stream() - .filter(method -> method.startsWith("lambda$outerWatchNestedLambdaTest$")) + // javac names the outer lambda lambda$$N and, depending on the + // compiler version, the inner nested lambda either lambda$$N or + // lambda$null$N, so count all collected lambda methods instead of one prefix. + long lambdaMethodCount = methods.stream() + .filter(method -> method.startsWith("lambda$")) .count(); - Assertions.assertEquals(2, nestedLambdaCount); + Assertions.assertEquals(2, lambdaMethodCount); } @Test @@ -415,10 +418,12 @@ public void outerWatchResultShouldReportReadableLambdaOuterDisplay() { Assertions.assertEquals("outerWatchNestedLambdaTest", changeTarget.outerWatchNestedLambdaTest()); OuterWatchResult result = (OuterWatchResult) swapResult.getData(); + // JDK 8 names the inner nested lambda lambda$null$N, JDK 17 uses + // lambda$$N; both must map to a readable [lambda$N] display. Assertions.assertTrue(result.getInspectedCalls().stream() .map(OuterWatchResult.InspectedCall::getOuterDisplay) .anyMatch(display -> display != null - && display.matches("w\\.core\\.ChangeTarget#outerWatchNestedLambdaTest\\[lambda\\$\\d+\\]"))); + && display.matches("w\\.core\\.ChangeTarget#[^\\[\\]]+\\[lambda\\$\\d+\\]"))); } @Test