Skip to content

Commit

Permalink
feat(objectionary#750): add one more unit test for frames computation
Browse files Browse the repository at this point in the history
  • Loading branch information
volodya-lombrozo committed Nov 2, 2024
1 parent 69b2e76 commit 066a5ea
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import lombok.EqualsAndHashCode;
Expand Down Expand Up @@ -361,6 +362,25 @@ BytecodeMaxs currentMaxs() {
return this.maxs;
}

/**
* Compute frames.
* @return Frames.
*/
List<BytecodeFrame> computeFrames() {
return Collections.emptyList();
}

/**
* Current frames.
* @return Frames.
*/
List<BytecodeFrame> currentFrames() {
return this.instructions.stream()
.filter(BytecodeFrame.class::isInstance)
.map(BytecodeFrame.class::cast)
.collect(Collectors.toList());
}

/**
* Add instruction.
* @param opcode Opcode.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.jcabi.matchers.XhtmlMatchers;
import com.jcabi.xml.XMLDocument;
import it.JavaSourceClass;
import java.util.List;
import java.util.UUID;
import java.util.stream.Stream;
import org.cactoos.bytes.BytesOf;
Expand Down Expand Up @@ -462,7 +463,7 @@ void visitsTableSwitchInstructionSuccessfully() throws ImpossibleModificationExc
}

@ParameterizedTest(name = "Computing maxs for method {1}, expected {2}")
@MethodSource("implementedMethods")
@MethodSource("implementedMaxs")
void computesMaxsCorrectlyForImplementedMethods(
final BytecodeMethod method,
final String name,
Expand All @@ -479,7 +480,7 @@ void computesMaxsCorrectlyForImplementedMethods(
}

@ParameterizedTest(name = "Computing maxs for method {1}, expected {2}")
@MethodSource("abstractMethods")
@MethodSource("abstractMaxs")
void computesMaxsCorrectlyForAbstractMethods(
final BytecodeMethod method,
final String name,
Expand All @@ -496,7 +497,7 @@ void computesMaxsCorrectlyForAbstractMethods(
}

@ParameterizedTest(name = "Computing maxs for method {1}, expected {2}")
@MethodSource("realMethods")
@MethodSource("realMaxs")
void computesMaxForRealClassAfterAllTransformations(
final BytecodeMethod method,
final String name,
Expand All @@ -513,15 +514,42 @@ void computesMaxForRealClassAfterAllTransformations(
);
}

@ParameterizedTest
@MethodSource("implementedFrames")
void computesStackMapFramesForSomeMethods(
final BytecodeMethod method,
final String name,
final List<BytecodeFrame> expected
) {
MatcherAssert.assertThat(
String.format(
"Stack map frames weren't computed correctly for method %s",
name
),
method.computeFrames(),
Matchers.equalTo(expected)
);
}

/**
* Provides implemented methods for testing.
* These methods contain different stack map frames.
* Used in {@link #computesStackMapFramesForSomeMethods(BytecodeMethod, String, List)}.
* @return Stream of argumentsForTesting().
*/
static Stream<Arguments> implementedFrames() {
return BytecodeMethodTest.methodFrames("maxs/Maxs.java");
}

/**
* Provides implemented methods for testing.
* These methods contain different number of local variables and stack elements.
* Used in
* {@link #computesMaxsCorrectlyForImplementedMethods(BytecodeMethod, String, BytecodeMaxs)}.
* @return Stream of arguments.
*/
static Stream<Arguments> implementedMethods() {
return BytecodeMethodTest.methods("maxs/Maxs.java");
static Stream<Arguments> implementedMaxs() {
return BytecodeMethodTest.methodMaxs("maxs/Maxs.java");
}

/**
Expand All @@ -531,21 +559,21 @@ static Stream<Arguments> implementedMethods() {
* {@link #computesMaxsCorrectlyForImplementedMethods(BytecodeMethod, String, BytecodeMaxs)}.
* @return Stream of arguments.
*/
static Stream<Arguments> abstractMethods() {
return BytecodeMethodTest.methods("maxs/MaxInterface.java");
static Stream<Arguments> abstractMaxs() {
return BytecodeMethodTest.methodMaxs("maxs/MaxInterface.java");
}

/**
* Provides methods for testing from real bytecode that is used in real projects.
* Before that, we disassemble and assemble the compiled class.
* @return Stream of arguments.
*/
static Stream<Arguments> realMethods() {
static Stream<Arguments> realMaxs() {
return Stream.of(
"AbstractEndpoint.class",
"FastHttpDateFormat.class",
"ByteArrayClassLoader$ChildFirst$PrependingEnumeration.class"
).flatMap(BytecodeMethodTest::disassembleAssemble);
).flatMap(BytecodeMethodTest::realMaxs);
}

/**
Expand All @@ -555,7 +583,7 @@ static Stream<Arguments> realMethods() {
* @checkstyle IllegalCatchCheck (25 lines)
*/
@SuppressWarnings("PMD.AvoidCatchingGenericException")
static Stream<Arguments> disassembleAssemble(final String compiled) {
static Stream<Arguments> realMaxs(final String compiled) {
try {
return new XmlProgram(
new BytecodeRepresentation(
Expand All @@ -581,11 +609,24 @@ static Stream<Arguments> disassembleAssemble(final String compiled) {
* @param clazz Resource class name.
* @return Stream of arguments.
*/
static Stream<Arguments> methods(final String clazz) {
static Stream<Arguments> methodMaxs(final String clazz) {
return new AsmProgram(
new JavaSourceClass(clazz).compile().bytes()
).bytecode().top().methods().stream().map(
method -> Arguments.of(method, method.name(), method.currentMaxs())
);
}

/**
* Provides method frames for testing.
* @param clazz Resource class name.
* @return Stream of arguments.
*/
static Stream<Arguments> methodFrames(final String clazz) {
return new AsmProgram(
new JavaSourceClass(clazz).compile().bytes()
).bytecode().top().methods().stream().map(
method -> Arguments.of(method, method.name(), method.currentFrames())
);
}
}

0 comments on commit 066a5ea

Please sign in to comment.