Skip to content

Commit eb0bc27

Browse files
authored
64 json e2e test (#131)
* Add first case for e2e json test in go * Impl CI and automate client servers for json e2e test * Put e2e test in it ci stage * Fix ci go version in client test * Fix setup go in ci * Move e2e test to maven module to ease ci cache and run * Remove server lifecycle management from java e2e test * Set ci host os version * Add json e2e test for java time * Add json e2e for generic class * Add json e2e for cyclic class * Add json e2e for map classes * Add json e2e for array class * Add json e2e for complex record * Add json e2e for math types * Add typescript server * Add value validations in typescript client server for json e2e test * Add rust http server * Fix rust http port * Use enum value type for Rust struct enum field type * Add TagLiterals annotion * Impl rust server to handle different types for json e2e test * Allow config tag literals for fields and methods * Save tagLiterals in components * Populate tagLiterals in CompositeTypeDefParser * Emit tagLiterals for rust code * Add JavaRecord for rust e2e test * Map enumValue type for rust map key * Fix JavaRecord * Add tag literals to all applicable templates * Set permission to ci * Increase e2e ready check timeout
1 parent 0fda5be commit eb0bc27

127 files changed

Lines changed: 3591 additions & 399 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yaml

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
name: CI
2+
permissions:
3+
contents: read
4+
pull-requests: write
25
on:
36
push:
47
branches:
@@ -7,15 +10,21 @@ on:
710
branches:
811
- master
912

13+
env:
14+
JAVA_VERSION: 21
15+
NODE_VERSION: 22
16+
GO_VERSION: 1.24
17+
RUST_VERSION: 1.83.0
18+
1019
jobs:
1120
style_check:
12-
runs-on: ubuntu-24.04
21+
runs-on: ubuntu-latest
1322
steps:
1423
- uses: actions/checkout@v4
1524
- uses: actions/setup-java@v4
1625
with:
1726
distribution: 'temurin'
18-
java-version: 21
27+
java-version: ${{env.JAVA_VERSION}}
1928
- uses: actions/cache@v4
2029
with:
2130
path: ~/.m2/repository
@@ -30,7 +39,7 @@ jobs:
3039
- uses: actions/setup-java@v4
3140
with:
3241
distribution: 'temurin'
33-
java-version: 21
42+
java-version: ${{env.JAVA_VERSION}}
3443
- uses: actions/cache@v4
3544
with:
3645
path: ~/.m2/repository
@@ -52,8 +61,7 @@ jobs:
5261
uses: actions/upload-artifact@v4
5362
with:
5463
name: jars
55-
path: |
56-
~/.m2/repository/online/sharedtype
64+
path: ~/.m2/repository/online/sharedtype
5765
if-no-files-found: error
5866
retention-days: 3
5967
- name: Remove jars from cache
@@ -77,7 +85,7 @@ jobs:
7785
path: ~/.m2/repository/online/sharedtype
7886
# - name: Display downloaded artifact
7987
# run: ls -lhR ~/.m2/repository/online/sharedtype
80-
- uses: actions/cache@v4
88+
- uses: actions/cache/restore@v4
8189
with:
8290
path: ~/.m2/repository
8391
key: build_maven
@@ -91,7 +99,7 @@ jobs:
9199
- uses: actions/checkout@v4
92100
- uses: actions/setup-node@v4
93101
with:
94-
node-version: 22
102+
node-version: ${{env.NODE_VERSION}}
95103
- uses: actions/download-artifact@v4
96104
with:
97105
name: generated-sources
@@ -106,17 +114,35 @@ jobs:
106114
107115
- uses: actions-rust-lang/setup-rust-toolchain@v1
108116
with:
109-
toolchain: 1.83.0
117+
toolchain: ${{env.RUST_VERSION}}
110118
- name: Test Rust
111119
working-directory: client-test/rust
112120
run: cargo test
113121

114122
- uses: actions/setup-go@v5
115123
with:
116-
go-version: 1.24
124+
cache-dependency-path: client-test/go/go.sum
125+
go-version-file: client-test/go/go.mod
117126
- name: Test Golang
118127
working-directory: client-test/go
119-
run: go get && go test
128+
run: go get && go test ./...
129+
130+
- uses: actions/setup-java@v4
131+
with:
132+
distribution: 'temurin'
133+
java-version: ${{env.JAVA_VERSION}}
134+
- uses: actions/cache/restore@v4
135+
with:
136+
path: ~/.m2/repository
137+
key: build_maven
138+
- uses: actions/download-artifact@v4
139+
with:
140+
name: jars
141+
path: ~/.m2/repository/online/sharedtype
142+
- name: E2E Test
143+
run: |
144+
misc/start-client-servers.sh &
145+
./mvnw verify -Pe2e -e --ntp -B
120146
121147
# clean-artifact:
122148
# needs: [ jdk_compatibility_test, client_test ]

annotation/src/main/java/online/sharedtype/SharedType.java

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.lang.annotation.Documented;
44
import java.lang.annotation.ElementType;
5+
import java.lang.annotation.Repeatable;
56
import java.lang.annotation.Retention;
67
import java.lang.annotation.RetentionPolicy;
78
import java.lang.annotation.Target;
@@ -242,9 +243,11 @@
242243
* Whether to mark generated type fields as readonly. Default fallback to global properties.
243244
*
244245
* @return value can be one of:
245-
* "all" - all fields are readonly
246-
* "acyclic" - only fields of not cyclic-referenced types are readonly
247-
* "none" - no fields are readonly
246+
* <ul>
247+
* <li>"all" - all fields are readonly</li>
248+
* <li>"acyclic" - only fields of not cyclic-referenced types are readonly</li>
249+
* <li>"none" - no fields are readonly</li>
250+
* </ul>
248251
*/
249252
String typescriptFieldReadonlyType() default "";
250253

@@ -301,7 +304,6 @@
301304
* The enum value must be "compile-time resolvable" in enum constant expressions (See "Constant" section in {@link SharedType}).
302305
* Note: When there are multiple enum constant constructor parameters, the value is resolved by field order.
303306
* If the constructor parameter order is different from the field order, value will not be resolved correctly.
304-
* Additional custom annotation types can be configured via global properties.
305307
* <pre>
306308
* {@code
307309
* //A simple example:
@@ -315,13 +317,32 @@
315317
* type Enum = 1 | 2;
316318
* }
317319
* </pre>
318-
* <br>
320+
* Additional custom annotation types can be configured via global properties. E.g. {@code @JsonValue} in Jackson.
319321
*/
320322
@Target({ElementType.FIELD})
321323
@Retention(RetentionPolicy.CLASS)
322324
@interface EnumValue {
323325
}
324326

327+
/**
328+
* Add any tag literals to a field. E.g.
329+
* <pre>
330+
* {@code
331+
* @SharedType.TagLiterals(tags = "#[serde(skip)]", targets = RUST)
332+
* private final Object ignoredField;
333+
* }
334+
* </pre>
335+
* It's treated as plain string, thus can also be used to emit comments or documentation.
336+
*/
337+
@Target({ElementType.FIELD, ElementType.METHOD})
338+
@Retention(RetentionPolicy.SOURCE)
339+
@Repeatable(TagLiterals.class)
340+
@interface TagLiteral {
341+
String[] tags();
342+
/** If empty, fallback to globally enabled targets. */
343+
TargetType[] targets() default {};
344+
}
345+
325346
enum ComponentType {
326347
/**
327348
* Represents:
@@ -360,4 +381,8 @@ enum OptionalBool {
360381
*/
361382
DEFAULT,
362383
}
384+
385+
enum TargetType {
386+
TYPESCRIPT, GO, RUST
387+
}
363388
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package online.sharedtype;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
@Target({ElementType.FIELD})
9+
@Retention(RetentionPolicy.SOURCE)
10+
public @interface TagLiterals {
11+
SharedType.TagLiteral[] value();
12+
}

client-test/go/go.mod

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ module sharedtype.online/go-client-test
22

33
go 1.23.2
44

5+
require (
6+
github.com/go-chi/chi/v5 v5.2.1
7+
github.com/stretchr/testify v1.10.0
8+
)
9+
510
require (
611
github.com/davecgh/go-spew v1.1.1 // indirect
712
github.com/pmezard/go-difflib v1.0.0 // indirect
8-
github.com/stretchr/testify v1.10.0 // indirect
913
gopkg.in/yaml.v3 v3.0.1 // indirect
1014
)

client-test/go/go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
22
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
4+
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
35
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
46
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
57
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
68
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
9+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
710
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
811
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
912
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

client-test/go/main_test.go

Lines changed: 0 additions & 26 deletions
This file was deleted.

client-test/go/server.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"log/slog"
7+
"net/http"
8+
9+
"github.com/go-chi/chi/v5"
10+
"github.com/go-chi/chi/v5/middleware"
11+
"sharedtype.online/go-client-test/sharedtype"
12+
)
13+
14+
func main() {
15+
r := chi.NewRouter()
16+
r.Use(middleware.Logger)
17+
r.Get("/health", func(w http.ResponseWriter, r *http.Request) {
18+
w.Write([]byte(`ok`))
19+
})
20+
r.Post("/{typeName}", route)
21+
fmt.Println("Server started on :3001, waiting for requests...")
22+
http.ListenAndServe(":3001", r)
23+
defer fmt.Println("Server stopped.")
24+
}
25+
26+
func route(w http.ResponseWriter, r *http.Request) {
27+
typeName := chi.URLParam(r, "typeName")
28+
res := createStruct(typeName)
29+
30+
if res == nil {
31+
http.Error(w, fmt.Sprintf("Unknown typeName: %s", typeName), 400)
32+
return
33+
}
34+
35+
if err := json.NewDecoder(r.Body).Decode(res); err != nil {
36+
http.Error(w, err.Error(), 400)
37+
slog.Error("Failed to decode request body", "error", err)
38+
return
39+
}
40+
41+
w.Header().Set("Content-Type", "application/json")
42+
43+
if err := json.NewEncoder(w).Encode(res); err != nil {
44+
http.Error(w, err.Error(), 500)
45+
return
46+
}
47+
}
48+
49+
func createStruct(typename string) any {
50+
switch typename {
51+
case "JavaClass":
52+
return &sharedtype.JavaClass{}
53+
case "JavaTimeClass":
54+
return &sharedtype.JavaTimeClass{}
55+
case "SubtypeWithNestedCustomTypeString":
56+
return &sharedtype.SubtypeWithNestedCustomTypeString{}
57+
case "DependencyClassA":
58+
return &sharedtype.DependencyClassA{}
59+
case "MapClass":
60+
return &sharedtype.MapClass{}
61+
case "ArrayClass":
62+
return &sharedtype.ArrayClass{}
63+
case "JavaRecord":
64+
return &sharedtype.JavaRecord[string]{}
65+
case "MathClass":
66+
return &sharedtype.MathClass{}
67+
default:
68+
return nil
69+
}
70+
}

client-test/go/sharedtype/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../it/java17/target/generated-sources/types.go
Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
package sharedtype
22

3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
)
8+
9+
func TestMain(t *testing.T) {
10+
dependencyClassC1.A = dependencyClassA1
11+
12+
RecursiveClass1.DirectRef = &RecursiveClass{
13+
DirectRef: nil,
14+
ArrayRef: []RecursiveClass{},
15+
}
16+
17+
OptionalMethods1.MapNestedValueOptional = &map[int32]string{1: "foo"}
18+
OptionalMethods1.SetNestedValueOptional = &[]string{"foo", "bar"}
19+
OptionalMethods1.NestedValueOptional = &List1[0]
20+
}
21+
22+
func TestConstants(t *testing.T) {
23+
assert.Equal(t, float32(1.888), FLOAT_VALUE)
24+
assert.Equal(t, "MilkyWay", REFERENCED_ENUM_VALUE)
25+
assert.Equal(t, int32(1), MyEnumConstants.INT_VALUE)
26+
}
27+
328
var List1 = []EnumGalaxy{"Andromeda", "MilkyWay", "Triangulum"}
429
var Record1 = map[EnumTShirt]int32{
530
S: 1,
@@ -27,7 +52,7 @@ var dependencyClassA1 = &DependencyClassA{
2752
var Obj = JavaRecord[string]{
2853
BoxedBoolean: false,
2954
BoxedByte: 0,
30-
BoxedChar: 'a',
55+
BoxedChar: "a",
3156
BoxedDouble: 0,
3257
BoxedFloat: 0,
3358
BoxedInt: 0,
@@ -47,7 +72,7 @@ var Obj = JavaRecord[string]{
4772
Object: nil,
4873
PrimitiveBoolean: false,
4974
PrimitiveByte: 0,
50-
PrimitiveChar: 'b',
75+
PrimitiveChar: "b",
5176
PrimitiveDouble: 0,
5277
PrimitiveFloat: 0,
5378
PrimitiveInt: 0,

client-test/go/types.go

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)