Skip to content

Commit

Permalink
Unit tests generation in Kotlin (hyperledger-web3j#1145)
Browse files Browse the repository at this point in the history
* Added Kotlin Poet as dependency.
Draft Implementation of parsing a Java Class and generating the Unit Tests.

* Additional changes to parser.
Separated classes into java and kotlin packages

* Fixed assertion generation in Kotlin.

* General refactoring.

* Fixed Tuple Generation.
Mapped correct types for arrays in kotlin.

* Added equivalent junit tests for kotlin generator.

* Replaced uppercase letter in package name with lowercase.

* Removed sun package usage.

* Spotless.

* Added annotation required by kotlin to run @BeforeAll.
Removed 'val' from deploy method.

* Fixed BigInteger import not being auto generated.
  • Loading branch information
AlexandrouR authored Jan 28, 2020
1 parent a793461 commit 6a6536e
Show file tree
Hide file tree
Showing 34 changed files with 2,076 additions and 268 deletions.
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ plugins {
ext {
bouncycastleVersion = '1.61'
jacksonVersion = '2.8.5'
javapoetVersion = '1.7.0'
javaPoetVersion = '1.7.0'
kotlinPoetVersion = '1.5.0'
jnr_unixsocketVersion = '0.21'
okhttpVersion = '4.3.1'
rxjavaVersion = '2.2.2'
Expand Down
3 changes: 2 additions & 1 deletion codegen/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ description 'web3j project code generators'

dependencies {
compile project(':core'),
"com.squareup:javapoet:$javapoetVersion",
"com.squareup:kotlinpoet:$kotlinPoetVersion",
"com.squareup:javapoet:$javaPoetVersion",
"info.picocli:picocli:$picocliVersion"
testCompile project(path: ':core', configuration: 'testArtifacts')
implementation("org.junit.platform:junit-platform-launcher:$junitPlatformLauncherVersion")
Expand Down
26 changes: 26 additions & 0 deletions codegen/src/main/java/org/web3j/codegen/unit/gen/MethodFilter.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,16 @@
package org.web3j.codegen.unit.gen;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

import com.squareup.javapoet.MethodSpec;
import com.squareup.kotlinpoet.FunSpec;

import org.web3j.codegen.unit.gen.java.MethodParser;
import org.web3j.codegen.unit.gen.kotlin.FunParser;
import org.web3j.protocol.Web3j;
import org.web3j.tx.TransactionManager;
import org.web3j.tx.gas.ContractGasProvider;
Expand Down Expand Up @@ -44,4 +50,24 @@ private static boolean parametersAreMatching(final Method method) {
}
return true;
}

public static List<MethodSpec> generateMethodSpecsForEachTest(Class theContract) {
List<MethodSpec> listOfMethodSpecs = new ArrayList<>();
extractValidMethods(theContract)
.forEach(
method ->
listOfMethodSpecs.add(
new MethodParser(method, theContract).getMethodSpec()));
return listOfMethodSpecs;
}

public static List<FunSpec> generateFunctionSpecsForEachTest(Class theContract) {
List<FunSpec> listOfMethodSpecs = new ArrayList<>();
extractValidMethods(theContract)
.forEach(
method ->
listOfMethodSpecs.add(
new FunParser(method, theContract).getFunSpec()));
return listOfMethodSpecs;
}
}
111 changes: 111 additions & 0 deletions codegen/src/main/java/org/web3j/codegen/unit/gen/Parser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright 2020 Web3 Labs Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.web3j.codegen.unit.gen;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.jupiter.api.Assertions;

import org.web3j.codegen.unit.gen.utils.MappingHelper;
import org.web3j.protocol.core.methods.response.TransactionReceipt;

import static org.web3j.codegen.unit.gen.utils.NameUtils.returnTypeAsLiteral;
import static org.web3j.codegen.unit.gen.utils.NameUtils.toCamelCase;

public abstract class Parser {

protected final MappingHelper mappingHelper;
protected final Class<?> theContract;
protected final Method method;

public Parser(Class<?> theContract, Method method, MappingHelper mappingHelper) {
this.theContract = theContract;
this.method = method;
this.mappingHelper = mappingHelper;
}

protected abstract Object getDefaultValueForType(Class<?> type);

protected abstract String generatePoetStringTypes();

protected abstract String getPoetFormatSpecifier();

protected final Object[] replaceTypeWithDefaultValue() {
return Arrays.stream(method.getParameterTypes())
.map(this::getDefaultValueForType)
.toArray();
}

public final Type getMethodReturnType() {
Type genericType = method.getGenericReturnType();
if (genericType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) genericType;
return parameterizedType.getActualTypeArguments()[0];
} else {
return genericType;
}
}

protected final Type[] getTypeArray(Type type) {
ParameterizedType parameterizedType = (ParameterizedType) type;
return parameterizedType.getActualTypeArguments();
}

public final Object[] generateAssertionPlaceholderValues() {
Type returnType = getMethodReturnType();
Object[] body = generatePlaceholderValues();
List<Object> placeHolder = new ArrayList<>();
placeHolder.add(Assertions.class);
if (!body[0].equals(TransactionReceipt.class)) {
if (returnType.getTypeName().contains("Tuple")) {
placeHolder.add(((ParameterizedType) returnType).getRawType());
for (Type t : getTypeArray(returnType)) {
placeHolder.add(mappingHelper.getDefaultValueMap().get(t));
}
} else {
placeHolder.add(mappingHelper.getDefaultValueMap().get(body[0]));
}
}
placeHolder.add(toCamelCase(returnTypeAsLiteral(returnType, true)));
return placeHolder.toArray();
}

public final Object[] generatePlaceholderValues() {
return mergePlaceholderValues(concludeMethodReturnType(), replaceTypeWithDefaultValue());
}

protected final Object[] mergePlaceholderValues(Object[] source1, Object[] source2) {
Object[] destination = new Object[source1.length + source2.length];
System.arraycopy(source1, 0, destination, 0, source1.length);
System.arraycopy(source2, 0, destination, source1.length, source2.length);
return destination;
}

protected final Object[] concludeMethodReturnType() {
Type returnType = getMethodReturnType();
if (returnType.equals(theContract)) {
return new Object[] {toCamelCase(returnTypeAsLiteral(returnType, false)), returnType};
} else {
return new Object[] {
returnType,
toCamelCase(returnTypeAsLiteral(returnType, true)),
toCamelCase(theContract)
};
}
}
}
165 changes: 0 additions & 165 deletions codegen/src/main/java/org/web3j/codegen/unit/gen/ParserUtils.java

This file was deleted.

Loading

0 comments on commit 6a6536e

Please sign in to comment.