Skip to content

Commit e8a2452

Browse files
committed
ci: build one GraalVM JSON image
1 parent e21497f commit e8a2452

4 files changed

Lines changed: 136 additions & 410 deletions

File tree

ci/run_ci.sh

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@ install_jdks() {
7979
done
8080
}
8181

82-
run_graalvm_tests() {
83-
local main_classes=("$@")
82+
run_graalvm_test() {
83+
local main_class="$1"
8484
local java_version
8585
local java_major
8686
java_version=$(java -version 2>&1 | awk -F '"' '/version/ {print $2; exit}')
@@ -103,25 +103,21 @@ run_graalvm_tests() {
103103
-Dmaven.source.skip=true \
104104
-Dmaven.javadoc.skip=true
105105
cd "$ROOT"/integration_tests/graalvm_tests
106-
for main_class in "${main_classes[@]}"; do
107-
echo "Start to build GraalVM JPMS native image for $main_class"
108-
mvn -DmainClass="$main_class" -DskipTests=true -Dassembly.skipAssembly=true \
109-
--no-transfer-progress -Pnative-module clean package
110-
echo "Built GraalVM JPMS native image"
111-
echo "Start to run GraalVM JPMS native image"
112-
./target/main-module
113-
echo "Execute GraalVM tests for $main_class succeed!"
114-
done
106+
echo "Start to build GraalVM JPMS native image for $main_class"
107+
mvn -DmainClass="$main_class" -DskipTests=true -Dassembly.skipAssembly=true \
108+
--no-transfer-progress -Pnative-module clean package
109+
echo "Built GraalVM JPMS native image"
110+
echo "Start to run GraalVM JPMS native image"
111+
./target/main-module
112+
echo "Execute GraalVM tests for $main_class succeed!"
115113
}
116114

117115
graalvm_test() {
118-
run_graalvm_tests org.apache.fory.graalvm.Main
116+
run_graalvm_test org.apache.fory.graalvm.Main
119117
}
120118

121119
graalvm_json_tests() {
122-
run_graalvm_tests \
123-
org.apache.fory.graalvm.ForyJsonExample \
124-
org.apache.fory.graalvm.ForyJsonNoProviderExample
120+
run_graalvm_test org.apache.fory.graalvm.ForyJsonExample
125121
}
126122

127123
jdk25_access_options() {

integration_tests/graalvm_tests/README.md

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# GraalVM Native Image Tests
22

3-
Examples and tests for Fory serialization in GraalVM Native Image. The Fory JSON entry points are
4-
compiled with annotation processing disabled. They cover direct `JsonType` models, exact
3+
Examples and tests for Fory serialization in GraalVM Native Image. The Fory JSON entry point is
4+
compiled with annotation processing disabled. It covers direct `JsonType` models, exact
55
`JsonMixin` target/source mappings, provider-selected hosted codec generation, configuration
6-
fallback to interpreted codecs, and a separate image with no reachable `ForyJsonProvider`.
6+
fallback to interpreted codecs, and hosted access metadata for unprovided configurations in one
7+
native image.
78

89
## Test
910

@@ -12,11 +13,6 @@ mvn -DmainClass=org.apache.fory.graalvm.ForyJsonExample clean -DskipTests=true -
1213
./target/main
1314
mvn -DmainClass=org.apache.fory.graalvm.ForyJsonExample clean -DskipTests=true -Pnative-module package
1415
./target/main-module
15-
16-
mvn -DmainClass=org.apache.fory.graalvm.ForyJsonNoProviderExample clean -DskipTests=true -Dexec.skip=true -Pnative package
17-
./target/main
18-
mvn -DmainClass=org.apache.fory.graalvm.ForyJsonNoProviderExample clean -DskipTests=true -Pnative-module package
19-
./target/main-module
2016
```
2117

2218
## Benchmark

integration_tests/graalvm_tests/src/main/java/org/apache/fory/graalvm/ForyJsonExample.java

Lines changed: 121 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@
4444
import org.apache.fory.json.ForyJson;
4545
import org.apache.fory.json.PropertyNamingStrategy;
4646
import org.apache.fory.json.annotation.ForyJsonProvider;
47+
import org.apache.fory.json.annotation.JsonAnyGetter;
4748
import org.apache.fory.json.annotation.JsonAnyProperty;
49+
import org.apache.fory.json.annotation.JsonAnySetter;
4850
import org.apache.fory.json.annotation.JsonBase64;
4951
import org.apache.fory.json.annotation.JsonCodec;
5052
import org.apache.fory.json.annotation.JsonCreator;
@@ -123,16 +125,14 @@ public static void main(String[] args) {
123125
}
124126

125127
private static void testHostedCodegenConfigurations() {
128+
ForyJson providerJson = newProviderJson();
129+
ForyJson interpretedJson = newInterpretedJson();
126130
exerciseCodegenConfiguration(ForyJson.builder().build(), false);
127-
exerciseCodegenConfiguration(newProviderJson(), true);
128-
exerciseCodegenConfiguration(
129-
ForyJson.builder()
130-
.withFieldMode(true)
131-
.withPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
132-
.registerCodec(CodegenProbeValue.class, new CodegenProbeCodec())
133-
.build(),
134-
false);
135-
testEmptyMixinCodegen();
131+
exerciseCodegenConfiguration(providerJson, true);
132+
exerciseCodegenConfiguration(interpretedJson, false);
133+
testEmptyMixin(providerJson, true);
134+
testEmptyMixin(interpretedJson, false);
135+
testInterpretedMetadata(interpretedJson);
136136
testIndependentChildCodegen();
137137
testExternalModuleMixin();
138138
}
@@ -147,16 +147,48 @@ private static ForyJson newProviderJson() {
147147
.build();
148148
}
149149

150-
private static void testEmptyMixinCodegen() {
151-
CodegenProbeCodec.expect(EmptyMixinTarget.class, true);
152-
ForyJson json = newProviderJson();
150+
private static ForyJson newInterpretedJson() {
151+
return ForyJson.builder()
152+
.withPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
153+
.registerCodec(CodegenProbeValue.class, new CodegenProbeCodec())
154+
.registerMixin(EmptyMixin.class)
155+
.registerMixin(InterpretedMixin.class)
156+
.build();
157+
}
158+
159+
private static void testEmptyMixin(ForyJson json, boolean generated) {
160+
CodegenProbeCodec.expect(EmptyMixinTarget.class, generated);
153161
EmptyMixinTarget value = new EmptyMixinTarget();
154162
value.probe = new CodegenProbeValue("empty-mixin");
155163
String encoded = json.toJson(value);
156164
Preconditions.checkArgument(
157165
json.fromJson(encoded, EmptyMixinTarget.class).probe.value.equals("empty-mixin"));
158166
}
159167

168+
private static void testInterpretedMetadata(ForyJson json) {
169+
InterpretedMixinTarget mixinValue = new InterpretedMixinTarget();
170+
mixinValue.setName("empty-mixin");
171+
String mixinJson = json.toJson(mixinValue);
172+
Preconditions.checkArgument(
173+
json.fromJson(mixinJson, InterpretedMixinTarget.class).getName().equals("empty-mixin"));
174+
175+
InterpretedBean bean = new InterpretedBean();
176+
bean.setName("bean");
177+
bean.putExtra("dynamic", "extra");
178+
InterpretedBean decoded = json.fromJson(json.toJson(bean), InterpretedBean.class);
179+
Preconditions.checkArgument(decoded.getName().equals("bean"));
180+
Preconditions.checkArgument(decoded.extra().equals(Map.of("dynamic", "extra")));
181+
182+
DirectValueRecord record = new DirectValueRecord("record-value");
183+
Preconditions.checkArgument(json.toJson(record).equals("\"record-value\""));
184+
Preconditions.checkArgument(
185+
json.fromJson("\"decoded-record\"", DirectValueRecord.class)
186+
.equals(new DirectValueRecord("decoded-record")));
187+
Preconditions.checkArgument(json.toJson(DirectValueEnum.READY).equals("\"ready\""));
188+
Preconditions.checkArgument(
189+
json.fromJson("\"done\"", DirectValueEnum.class) == DirectValueEnum.DONE);
190+
}
191+
160192
private static void exerciseCodegenConfiguration(ForyJson json, boolean generated) {
161193
CodegenProbeCodec.expect(CodegenProbeModel.class, generated);
162194
CodegenProbeModel value = new CodegenProbeModel();
@@ -437,6 +469,7 @@ private static void testValueAnnotations() {
437469
Preconditions.checkArgument(
438470
Arrays.equals(
439471
json.fromJson("{\"value\":\"AQID\"}", Base64Bytes.class).value, new byte[] {1, 2, 3}));
472+
440473
}
441474

442475
private static void testSubtypes() {
@@ -547,6 +580,49 @@ public EmptyMixinTarget() {}
547580
@JsonMixin(target = EmptyMixinTarget.class)
548581
public interface EmptyMixin {}
549582

583+
public static final class InterpretedMixinTarget {
584+
private String name;
585+
586+
public InterpretedMixinTarget() {}
587+
588+
public String getName() {
589+
return name;
590+
}
591+
592+
public void setName(String name) {
593+
this.name = name;
594+
}
595+
}
596+
597+
@JsonMixin(target = InterpretedMixinTarget.class)
598+
public interface InterpretedMixin {}
599+
600+
@JsonType
601+
public static final class InterpretedBean {
602+
private String name;
603+
private final transient Map<String, String> extra = new LinkedHashMap<>();
604+
605+
public InterpretedBean() {}
606+
607+
public String getName() {
608+
return name;
609+
}
610+
611+
public void setName(String name) {
612+
this.name = name;
613+
}
614+
615+
@JsonAnyGetter
616+
public Map<String, String> extra() {
617+
return extra;
618+
}
619+
620+
@JsonAnySetter
621+
public void putExtra(String key, String value) {
622+
extra.put(key, value);
623+
}
624+
}
625+
550626
/** Hosted-only loader which makes the first equivalent provider unable to compile one model. */
551627
public static final class CodegenRejectingClassLoader extends ClassLoader {
552628
public CodegenRejectingClassLoader() {
@@ -838,6 +914,39 @@ public String value() {
838914
}
839915
}
840916

917+
@JsonType
918+
public record DirectValueRecord(@JsonValue String value) {
919+
@JsonCreator
920+
public DirectValueRecord {}
921+
}
922+
923+
@JsonType
924+
public enum DirectValueEnum {
925+
READY("ready"),
926+
DONE("done");
927+
928+
private final String value;
929+
930+
DirectValueEnum(String value) {
931+
this.value = value;
932+
}
933+
934+
@JsonValue
935+
public String value() {
936+
return value;
937+
}
938+
939+
@JsonCreator
940+
public static DirectValueEnum fromValue(String value) {
941+
for (DirectValueEnum candidate : values()) {
942+
if (candidate.value.equals(value)) {
943+
return candidate;
944+
}
945+
}
946+
throw new IllegalArgumentException(value);
947+
}
948+
}
949+
841950
@JsonType
842951
public static final class RawValue {
843952
@JsonRawValue public String body;

0 commit comments

Comments
 (0)