Skip to content

Commit e09a611

Browse files
authored
Drop using gson and add test coverage (#49)
* replace gson to jackson * add test coverage
1 parent 433f893 commit e09a611

32 files changed

+274
-152
lines changed

.github/workflows/gradle.yml

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,17 @@ jobs:
1010
build:
1111
runs-on: ubuntu-latest
1212
permissions:
13+
checks: write
1314
contents: write
1415
pull-requests: write
1516

1617
steps:
1718
- uses: actions/checkout@v4
18-
19-
- name: Set up JDK 21
20-
uses: actions/setup-java@v4
19+
- name: Set up JDK 25
20+
uses: actions/setup-java@v5
2121
with:
22-
java-version: '21'
22+
java-version: '25'
2323
distribution: 'temurin'
24-
2524
- name: Setup Gradle
2625
uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
2726

@@ -31,17 +30,42 @@ jobs:
3130
- name: Run tests for all modules
3231
run: ./gradlew test
3332

33+
- name: Generate test report
34+
uses: mikepenz/action-junit-report@v5
35+
if: success() || failure() # always run even if the previous step fails
36+
with:
37+
report_paths: '**/build/test-results/test/TEST-*.xml'
38+
summary: true
39+
detailed_summary: true
40+
require_passed_tests: true
41+
include_passed: true
42+
43+
- name: Generate jacoco reports
44+
run: ./gradlew jacocoTestReport
45+
46+
- name: Generate aggregated jacoco report
47+
run: ./gradlew test-coverage:testCodeCoverageReport
48+
49+
- name: Add coverage to PR
50+
id: jacoco
51+
uses: madrapps/[email protected]
52+
with:
53+
paths: ${{ github.workspace }}/test-coverage/build/reports/jacoco/testCodeCoverageReport/testCodeCoverageReport.xml
54+
token: ${{ secrets.GITHUB_TOKEN }}
55+
min-coverage-overall: 40
56+
min-coverage-changed-files: 60
57+
3458
dependency-submission:
3559
runs-on: ubuntu-latest
3660
permissions:
3761
contents: write
3862
steps:
3963
- uses: actions/checkout@v4
4064

41-
- name: Set up JDK 21
42-
uses: actions/setup-java@v4
65+
- name: Set up JDK 25
66+
uses: actions/setup-java@v5
4367
with:
44-
java-version: '21'
68+
java-version: '25'
4569
distribution: 'temurin'
4670

4771
- name: Generate and submit dependency graph

application/src/test/groovy/javasabr/mqtt/broker/application/service/DisabledFeaturesSubscribtionServiceTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class DisabledFeaturesSubscribtionServiceTest extends IntegrationSpecification {
3131
.send()
3232
.join()
3333
then:
34-
Thread.sleep(10)
34+
Thread.sleep(50)
3535
subscriber.state == MqttClientState.DISCONNECTED
3636
def ex = thrown CompletionException
3737
if (ex.cause != null) {

base/build.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
plugins {
22
id("java-library")
33
id("configure-java")
4+
id("groovy")
45
}
56

67
dependencies {
7-
api libs.gson
8+
api libs.jackson.core
9+
api libs.jackson.databind
810
api libs.project.reactor.core
911
api libs.rlib.collections
1012
testImplementation projects.testSupport
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
package javasabr.mqtt.base.util;
2+
3+
import com.fasterxml.jackson.annotation.JsonAutoDetect;
4+
import com.fasterxml.jackson.annotation.JsonFilter;
5+
import java.lang.StackWalker.Option;
6+
import java.util.Set;
7+
import java.util.concurrent.ConcurrentHashMap;
8+
import java.util.concurrent.ConcurrentMap;
9+
import javasabr.rlib.collections.array.Array;
10+
import tools.jackson.core.JacksonException;
11+
import tools.jackson.core.JsonGenerator;
12+
import tools.jackson.databind.SerializationContext;
13+
import tools.jackson.databind.SerializationFeature;
14+
import tools.jackson.databind.introspect.AnnotatedMember;
15+
import tools.jackson.databind.json.JsonMapper;
16+
import tools.jackson.databind.jsonFormatVisitors.JsonObjectFormatVisitor;
17+
import tools.jackson.databind.module.SimpleModule;
18+
import tools.jackson.databind.ser.PropertyFilter;
19+
import tools.jackson.databind.ser.PropertyWriter;
20+
import tools.jackson.databind.ser.std.SimpleFilterProvider;
21+
import tools.jackson.databind.ser.std.StdSerializer;
22+
23+
public class DebugUtils {
24+
25+
@JsonFilter("debugFieldsFilter")
26+
public static class DebugFieldsFilterMixIn {}
27+
28+
private static final ConcurrentMap<Class<?>, Set<String>> INCLUDED_DEBUG_PROPERTIES =
29+
new ConcurrentHashMap<>();
30+
31+
32+
private static class IncludeDebugFieldsPropertyFilter implements PropertyFilter {
33+
34+
@Override
35+
public void serializeAsProperty(
36+
Object pojo,
37+
JsonGenerator jsonGenerator,
38+
SerializationContext context,
39+
PropertyWriter writer)
40+
throws Exception {
41+
42+
AnnotatedMember member = writer.getMember();
43+
String name = member.getName();
44+
Class<?> declaringClass = member.getDeclaringClass();
45+
Set<String> fields = INCLUDED_DEBUG_PROPERTIES.get(declaringClass);
46+
47+
while (declaringClass != Object.class && fields == null) {
48+
declaringClass = declaringClass.getSuperclass();
49+
fields = INCLUDED_DEBUG_PROPERTIES.get(declaringClass);
50+
}
51+
52+
if (fields == null || fields.contains(name)) {
53+
writer.serializeAsProperty(pojo, jsonGenerator, context);
54+
}
55+
}
56+
57+
@Override
58+
public void serializeAsElement(
59+
Object elementValue,
60+
JsonGenerator jsonGenerator,
61+
SerializationContext context,
62+
PropertyWriter writer) throws Exception {
63+
writer.serializeAsElement(elementValue, jsonGenerator, context);
64+
}
65+
66+
@Override
67+
public void depositSchemaProperty(
68+
PropertyWriter writer,
69+
JsonObjectFormatVisitor objectFormatVisitor,
70+
SerializationContext context) {
71+
writer.depositSchemaProperty(objectFormatVisitor, context);
72+
}
73+
74+
@Override
75+
public PropertyFilter snapshot() {
76+
return this;
77+
}
78+
}
79+
80+
public static class ArraySerializer extends StdSerializer<Array<?>> {
81+
82+
public ArraySerializer() {
83+
super(Array.class);
84+
}
85+
86+
@Override
87+
public void serialize(
88+
Array<?> value,
89+
JsonGenerator gen,
90+
SerializationContext provider) throws JacksonException {
91+
gen.writeStartArray();
92+
for (Object element : value) {
93+
gen.writePOJO(element);
94+
}
95+
gen.writeEndArray();
96+
}
97+
}
98+
99+
private static final SimpleFilterProvider DEBUG_FIELDS_FILTER = new SimpleFilterProvider();
100+
private static final IncludeDebugFieldsPropertyFilter INCLUDE_DEBUG_FIELDS_PROPERTY_FILTER =
101+
new IncludeDebugFieldsPropertyFilter();
102+
103+
static {
104+
DEBUG_FIELDS_FILTER.addFilter("debugFieldsFilter", INCLUDE_DEBUG_FIELDS_PROPERTY_FILTER);
105+
}
106+
107+
private static final JsonMapper DEBUG_OBJECT_MAPPER = JsonMapper
108+
.builder()
109+
.enable(SerializationFeature.INDENT_OUTPUT)
110+
.changeDefaultVisibility(visibilityChecker -> visibilityChecker
111+
.withFieldVisibility(JsonAutoDetect.Visibility.ANY)
112+
.withGetterVisibility(JsonAutoDetect.Visibility.NONE)
113+
.withIsGetterVisibility(JsonAutoDetect.Visibility.NONE))
114+
.addMixIn(Object.class, DebugFieldsFilterMixIn.class)
115+
.addModule(new SimpleModule()
116+
.addSerializer(new ArraySerializer()))
117+
.filterProvider(DEBUG_FIELDS_FILTER)
118+
.build();
119+
120+
public static void registerIncludedFields(String... fieldNames) {
121+
122+
Class<?> callerClass = StackWalker
123+
.getInstance(Option.RETAIN_CLASS_REFERENCE)
124+
.getCallerClass();
125+
126+
INCLUDED_DEBUG_PROPERTIES.put(callerClass, Set.of(fieldNames));
127+
}
128+
129+
public static void registerIncludedFields(Class<?> callerClass, String... fieldNames) {
130+
INCLUDED_DEBUG_PROPERTIES.put(callerClass, Set.of(fieldNames));
131+
}
132+
133+
public static String toJsonString(Object object) {
134+
return DEBUG_OBJECT_MAPPER.writeValueAsString(object);
135+
}
136+
}

base/src/main/java/javasabr/mqtt/base/utils/ReactorUtils.java renamed to base/src/main/java/javasabr/mqtt/base/util/ReactorUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package javasabr.mqtt.base.utils;
1+
package javasabr.mqtt.base.util;
22

33
import java.util.function.BiFunction;
44
import java.util.function.Consumer;

base/src/main/java/javasabr/mqtt/base/utils/DebugUtils.java

Lines changed: 0 additions & 98 deletions
This file was deleted.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package javasabr.mqtt.base.util
2+
3+
import javasabr.mqtt.test.support.UnitSpecification
4+
import javasabr.rlib.collections.array.Array
5+
import javasabr.rlib.collections.array.ArrayFactory
6+
import javasabr.rlib.collections.array.MutableArray
7+
8+
class DebugUtilsTest extends UnitSpecification {
9+
10+
class TestData {
11+
String name = "testData"
12+
String ignored = "ignored"
13+
MutableArray<String> mutableValues = ArrayFactory.mutableArray(String)
14+
Array<String> values = ArrayFactory.mutableArray(String)
15+
Iterable<String> emptyArray = Array.empty(String)
16+
17+
TestData() {
18+
def array = ArrayFactory.mutableArray(String)
19+
array.add("First")
20+
array.add("Second")
21+
this.mutableValues = array;
22+
this.values = Array.copyOf(array)
23+
}
24+
25+
static {
26+
DebugUtils.registerIncludedFields(TestData,
27+
"name", "mutableValues", "values", "emptyArray")
28+
}
29+
30+
String toString() {
31+
return DebugUtils.toJsonString(this)
32+
}
33+
}
34+
35+
def "should correctly write class to json"() {
36+
given:
37+
def data = new TestData()
38+
when:
39+
def json = data.toString()
40+
then:
41+
json == """{
42+
"emptyArray" : [ ],
43+
"mutableValues" : [ "First", "Second" ],
44+
"name" : "testData",
45+
"values" : [ "First", "Second" ]
46+
}"""
47+
}
48+
}

0 commit comments

Comments
 (0)