Skip to content

Commit

Permalink
Improved existing code coverage (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
LachlanMcKee authored Aug 12, 2018
1 parent c8c7778 commit 47a011d
Show file tree
Hide file tree
Showing 44 changed files with 549 additions and 258 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ branches:
- develop

script:
- ./gradlew check
- if [ $TRAVIS_PULL_REQUEST != 'false' ];
then ./gradlew sonarqube -Dsonar.analysis.mode=preview -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=lachlanmckee-github -Dsonar.login=$SONAR_TOKEN -Dsonar.github.pullRequest=$TRAVIS_PULL_REQUEST -Dsonar.github.repository=LachlanMcKee/gsonpath -Dsonar.github.oauth=$GITHUB_TOKEN;
else ./gradlew sonarqube -Dsonar.analysis.mode=publish -Dsonar.host.url=https://sonarcloud.io -Dsonar.organization=lachlanmckee-github -Dsonar.login=$SONAR_TOKEN;
fi
- ./gradlew codeCoverageReport

before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
Expand Down
36 changes: 35 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,50 @@ plugins {
id "org.sonarqube" version "2.5"
}

apply plugin: 'jacoco'

jacoco {
toolVersion = "0.8.2-SNAPSHOT" // the snapshot ignores generated kotlin code
}

allprojects {
repositories {
jcenter()
maven {
url "https://oss.sonatype.org/content/repositories/snapshots/"
}
}
}


sonarqube {
properties {
property "sonar.projectName", "Gsonpath"
property "sonar.projectKey", "gsonpath"
}
}

task codeCoverageReport(type: JacocoReport) {
executionData fileTree(project.rootDir.absolutePath).include("**/build/jacoco/*.exec")

// Ignore extension code
def excludes = ['gsonpath/compiler/ExtensionFieldMetadata.class']

classDirectories = fileTree(dir: "gsonpath-compiler/build/classes/main") +
fileTree(dir: "gsonpath-compiler/build/kotlin-classes/main") +
fileTree(dir: "gsonpath-compiler-base/build/classes/main", excludes: excludes) +
fileTree(dir: "gsonpath-compiler-base/build/kotlin-classes/main", excludes: excludes)

sourceDirectories = files('gsonpath-compiler/src/main/java',
'gsonpath-compiler-base/src/main/java')

reports {
xml.enabled true
xml.destination "${buildDir}/reports/jacoco/report.xml"
html.enabled false
csv.enabled false
}
}

codeCoverageReport.dependsOn {
subprojects*.test
}
27 changes: 27 additions & 0 deletions gsonpath-compiler-tests-base/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
apply plugin: 'java'
apply plugin: 'kotlin'

targetCompatibility = JavaVersion.VERSION_1_7
sourceCompatibility = JavaVersion.VERSION_1_7

buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
compile project(":gsonpath-compiler")
compile "junit:junit:$junit_version"
compile "org.mockito:mockito-core:1.10.19"
compile "com.google.truth:truth:0.34"
compile "com.google.testing.compile:compile-testing:0.11"
compile files(org.gradle.internal.jvm.Jvm.current().getToolsJar())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package gsonpath.generator

import com.google.common.truth.Truth.assertAbout
import com.google.testing.compile.JavaFileObjects
import com.google.testing.compile.JavaSourceSubjectFactory.javaSource
import com.google.testing.compile.JavaSourcesSubjectFactory.javaSources
import com.google.testing.compile.ProcessedCompileTesterFactory
import gsonpath.GsonProcessorImpl
import javax.tools.JavaFileObject

object GeneratorTester {

fun assertGeneratedContent(criteria: TestCriteria) {
val sourceFilesSize = criteria.absoluteSourceNames.size + criteria.relativeSourceNames.size

// Add all the required 'source' files.
val testerFactory: ProcessedCompileTesterFactory = if (sourceFilesSize == 1) {
assertAbout(javaSource()).that(getSourceFileObject(criteria, 0))

} else {
// Since we have multiple sources, we need to use a slightly different assert.
val sources = (0 until sourceFilesSize).map { getSourceFileObject(criteria, it) }
assertAbout(javaSources()).that(sources)
}

testerFactory.processedWith(GsonProcessorImpl())
.compilesWithoutError()
.and()
.apply {
// Add all the required 'generated' files based off the input source files.
val generatedSources = (0 until criteria.relativeGeneratedNames.size).map {
getGeneratedFileObject(criteria, it)
}

if (generatedSources.size == 1) {
generatesSources(generatedSources.first())

} else {
generatesSources(generatedSources.first(),
*generatedSources.subList(1, generatedSources.size).toTypedArray())
}
}
}

private fun getSourceFileObject(criteria: TestCriteria, index: Int): JavaFileObject {
return criteria.let {
val relativeSize = it.relativeSourceNames.size
if (index < relativeSize) {
JavaFileObjects.forResource(it.resourcePath + "/" + it.relativeSourceNames[index])
} else {
JavaFileObjects.forResource(it.absoluteSourceNames[index - relativeSize])
}
}
}

private fun getGeneratedFileObject(criteria: TestCriteria, index: Int): JavaFileObject {
return criteria.let {
JavaFileObjects.forResource(it.resourcePath + "/" + it.relativeGeneratedNames[index])
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package gsonpath.generator

class TestCriteria(val resourcePath: String,
val relativeSourceNames: List<String> = emptyList(),
val relativeGeneratedNames: List<String> = emptyList(),
val absoluteSourceNames: List<String> = emptyList())
27 changes: 27 additions & 0 deletions gsonpath-compiler-tests-extension/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
apply plugin: 'java'
apply plugin: 'kotlin'
apply plugin: 'jacoco'

jacoco {
toolVersion = "0.8.2-SNAPSHOT" // the snapshot ignores generated kotlin code
}

targetCompatibility = JavaVersion.VERSION_1_8
sourceCompatibility = JavaVersion.VERSION_1_8

buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
mavenCentral()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}

dependencies {
compile project(":gsonpath-compiler")
testCompile project(":gsonpath-compiler-tests-base")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package gsonpath.extension;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import static java.lang.annotation.RetentionPolicy.RUNTIME;

/**
* Changes an empty string to a null value.
*/
@Retention(RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
@Inherited
public @interface EmptyStringToNull {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package gsonpath.extension

import com.squareup.javapoet.ClassName
import com.squareup.javapoet.CodeBlock
import gsonpath.ProcessingException
import gsonpath.compiler.ExtensionFieldMetadata
import gsonpath.compiler.GsonPathExtension
import gsonpath.compiler.addEscapedStatement

import javax.annotation.processing.ProcessingEnvironment

/**
* A {@link GsonPathExtension} that supports the '@Size' annotation.
*/
class TestExtension : GsonPathExtension {

override val extensionName: String
get() = "'EmptyStringToNull' Annotation"

override fun createFieldReadCodeBlock(processingEnvironment: ProcessingEnvironment,
extensionFieldMetadata: ExtensionFieldMetadata): CodeBlock? {

val (fieldInfo, variableName, jsonPath, isRequired) = extensionFieldMetadata

if (fieldInfo.getAnnotation(EmptyStringToNull::class.java) == null) {
return null
}

if ((fieldInfo.typeName != ClassName.get(String::class.java))) {
throw ProcessingException("Unexpected type found for field annotated with 'EmptyStringToNull', only " +
"string classes may be used.", fieldInfo.element)
}

return CodeBlock.builder()
.beginControlFlow("if ($variableName.trim().length() == 0)")
.apply {
if (isRequired) {
addEscapedStatement("throw new com.google.gson.JsonParseException(" +
"\"JSON element '$jsonPath' cannot be blank\")")
} else {
addStatement("$variableName = null")
}
}
.endControlFlow()
.build()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gsonpath.extension.TestExtension
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package gsonpath.generator

import gsonpath.generator.GeneratorTester.assertGeneratedContent
import org.junit.Test

class ExtensionTest {

@Test
fun testExcludeFields() {
assertGeneratedContent(TestCriteria("generator/standard",
relativeSourceNames = listOf(
"TestGsonTypeFactory.java",
"TestExtension.java"),

relativeGeneratedNames = listOf(
"TestExtension_GsonTypeAdapter.java")
))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package generator.standard;

import gsonpath.AutoGsonAdapter;
import gsonpath.extension.EmptyStringToNull;

@AutoGsonAdapter
public class TestExtension {
@EmptyStringToNull
public String element1;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package generator.standard;

import static gsonpath.GsonUtil.*;

import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.IOException;
import java.lang.Override;
import java.lang.String;
import javax.annotation.Generated;

@Generated(
value = "gsonpath.GsonProcessor",
comments = "https://github.com/LachlanMcKee/gsonpath"
)
public final class TestExtension_GsonTypeAdapter extends TypeAdapter<TestExtension> {
private final Gson mGson;

public TestExtension_GsonTypeAdapter(Gson gson) {
this.mGson = gson;
}

@Override
public TestExtension read(JsonReader in) throws IOException {
// Ensure the object is not null.
if (!isValidValue(in)) {
return null;
}
TestExtension result = new TestExtension();

int jsonFieldCounter0 = 0;
in.beginObject();

while (in.hasNext()) {
if (jsonFieldCounter0 == 1) {
in.skipValue();
continue;
}

switch (in.nextName()) {
case "element1":
jsonFieldCounter0++;

String value_element1 = mGson.getAdapter(String.class).read(in);
if (value_element1 != null) {
result.element1 = value_element1;
}

// Gsonpath Extensions
if (value_element1 != null) {

// Extension - 'EmptyStringToNull' Annotation
if (value_element1.trim().length() == 0) {
value_element1 = null;
}

}
break;

default:
in.skipValue();
break;
}
}

in.endObject();
return result;
}

@Override
public void write(JsonWriter out, TestExtension value) throws IOException {
if (value == null) {
out.nullValue();
return;
}

// Begin
out.beginObject();
String obj0 = value.element1;
if (obj0 != null) {
out.name("element1");
mGson.getAdapter(String.class).write(out, obj0);
}

// End
out.endObject();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package generator.standard;

import com.google.gson.TypeAdapterFactory;

import gsonpath.AutoGsonAdapterFactory;

@AutoGsonAdapterFactory
public interface TestGsonTypeFactory extends TypeAdapterFactory {
}
Loading

0 comments on commit 47a011d

Please sign in to comment.