From d80bf56b93865ddcd0f0893714e21a2c5b826fbe Mon Sep 17 00:00:00 2001 From: SparkChuang <100325591+SparkChuang@users.noreply.github.com> Date: Mon, 30 May 2022 10:54:50 +0800 Subject: [PATCH] support rdl file without version on parsec 2.1.7 (#75) --- .gitignore | 1 + .../gentemplate_test.go | 70 ++++++++++++ cmd/rdl-gen-parsec-java-client/main.go | 4 +- cmd/rdl-gen-parsec-java-model/main.go | 10 +- cmd/rdl-gen-parsec-java-model/main_test.go | 61 ++++++++++ .../genServerTemplate_test.go | 108 ++++++++++++++++++ cmd/rdl-gen-parsec-java-server/main.go | 22 +++- testdata/sampleWithVersion.rdl | 22 ++++ testdata/sampleWithoutVersion.rdl | 21 ++++ utils/java-util.go | 10 ++ 10 files changed, 319 insertions(+), 10 deletions(-) create mode 100644 cmd/rdl-gen-parsec-java-server/genServerTemplate_test.go create mode 100644 testdata/sampleWithVersion.rdl create mode 100644 testdata/sampleWithoutVersion.rdl diff --git a/.gitignore b/.gitignore index cc964f9..98c49b2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ target/ tests/generated/ *.iml *.rdl +!testdata/*.rdl \ No newline at end of file diff --git a/cmd/rdl-gen-parsec-java-client/gentemplate_test.go b/cmd/rdl-gen-parsec-java-client/gentemplate_test.go index bc36b34..553ab2e 100644 --- a/cmd/rdl-gen-parsec-java-client/gentemplate_test.go +++ b/cmd/rdl-gen-parsec-java-client/gentemplate_test.go @@ -8,6 +8,7 @@ import ( "io/ioutil" "encoding/json" "github.com/ardielle/ardielle-go/rdl" + "github.com/stretchr/testify/assert" "github.com/yahoo/parsec-rdl-gen/utils" "bufio" "bytes" @@ -113,3 +114,72 @@ func TestUriConstruct(test *testing.T) { realOut, expectedOut) } } + +func TestGenerateClientWithoutVersion(t *testing.T) { + testOutputDir := getTempDir(t, ".", "testOutput-") + path := testOutputDir + "/com/yahoo/shopping/parsec_generated/" + + //generate output result + schema, err := rdl.ParseRDLFile("../../testdata/sampleWithoutVersion.rdl", false, false, false) + if err != nil { + t.Fatalf("%v", err) + } + GenerateJavaClient("withoutVersion", schema, testOutputDir, string(schema.Namespace), "", false) + + //asserts + clientContent := checkAndGetFileContent(t, path, "SampleClient.java") + assert.Contains(t, string(clientContent), "CompletableFuture") + assert.Contains(t, string(clientContent), "postUser(User") + + clientImplContent := checkAndGetFileContent(t, path, "SampleClientImpl.java") + assert.Contains(t, string(clientImplContent), "CompletableFuture") + assert.Contains(t, string(clientImplContent), "postUser(User") + + //clean up folder + defer os.RemoveAll(testOutputDir) +} + +func TestGenerateClientWithVersion(t *testing.T) { + testOutputDir := getTempDir(t, ".", "testOutput-") + path := testOutputDir + "/com/yahoo/shopping/parsec_generated/" + + //generate output result + schema, err := rdl.ParseRDLFile("../../testdata/sampleWithVersion.rdl", false, false, false) + if err != nil { + t.Fatalf("%v", err) + } + GenerateJavaClient("withVersion", schema, testOutputDir, string(schema.Namespace), "", false) + + //asserts + clientContent := checkAndGetFileContent(t, path, "SampleClient.java") + assert.Contains(t, string(clientContent), "CompletableFuture") + assert.Contains(t, string(clientContent), "postUser(UserV2") + + clientImplContent := checkAndGetFileContent(t, path, "SampleClientImpl.java") + assert.Contains(t, string(clientImplContent), "CompletableFuture") + assert.Contains(t, string(clientImplContent), "postUser(UserV2") + + // clean up folder + defer os.RemoveAll(testOutputDir) +} + +func checkAndGetFileContent(t *testing.T, path string, fileName string) []byte { + //1. check correspanding client file exists + if _, err := os.Stat(path + fileName); err != nil { + t.Fatalf("file not exists: %s", path+fileName) + } + //2. check file content + content, err := os.ReadFile(path + fileName) + if err != nil { + t.Fatalf("can not read file: %s", path+fileName) + } + return content +} + +func getTempDir(t *testing.T, dir string, prefix string) string { + dir, err := ioutil.TempDir(dir, prefix) + if err != nil { + t.Fatalf("%v", err) + } + return dir +} diff --git a/cmd/rdl-gen-parsec-java-client/main.go b/cmd/rdl-gen-parsec-java-client/main.go index a520f06..db35b85 100644 --- a/cmd/rdl-gen-parsec-java-client/main.go +++ b/cmd/rdl-gen-parsec-java-client/main.go @@ -465,5 +465,7 @@ func (gen *javaClientGenerator) clientMethodOverloadContent(r *rdl.Resource) str } func (gen *javaClientGenerator) javaType(reg rdl.TypeRegistry, rdlType rdl.TypeRef, optional bool, items rdl.TypeRef, keys rdl.TypeRef) string { - return utils.JavaType(reg, rdlType, optional, items, keys, gen.isPcSuffix, *gen.schema.Version) + ver, err := utils.GetSchemaVersionOrDefault(gen.schema, 1) + checkErr(err) + return utils.JavaType(reg, rdlType, optional, items, keys, gen.isPcSuffix, ver) } diff --git a/cmd/rdl-gen-parsec-java-model/main.go b/cmd/rdl-gen-parsec-java-model/main.go index ab73597..1080492 100644 --- a/cmd/rdl-gen-parsec-java-model/main.go +++ b/cmd/rdl-gen-parsec-java-model/main.go @@ -142,7 +142,8 @@ func generateJavaType(banner string, schema *rdl.Schema, registry rdl.TypeRegist return nil } cName := utils.Capitalize(string(tName)) - ver := *schema.Version + ver, err := utils.GetSchemaVersionOrDefault(schema, 1) + checkErr(err) if ver > 1 { cName += "V" + strconv.Itoa(int(ver)) } @@ -594,7 +595,8 @@ func (gen *javaModelGenerator) generateEnum(t *rdl.Type) { } et := t.EnumTypeDef name := utils.Capitalize(string(et.Name)) - ver := *gen.schema.Version + ver, err := utils.GetSchemaVersionOrDefault(gen.schema, 1) + checkErr(err) if ver > 1 { name += "V" + strconv.Itoa(int(ver)) } @@ -939,7 +941,9 @@ func (gen *javaModelGenerator) getValidationGroupValue(annotationValue string) s } func (gen *javaModelGenerator) javaType(reg rdl.TypeRegistry, rdlType rdl.TypeRef, optional bool, items rdl.TypeRef, keys rdl.TypeRef) string { - return utils.JavaType(reg, rdlType, optional, items, keys, gen.isPcSuffix, *gen.schema.Version) + ver, err := utils.GetSchemaVersionOrDefault(gen.schema, 1) + checkErr(err) + return utils.JavaType(reg, rdlType, optional, items, keys, gen.isPcSuffix, ver) } func javaFieldName(n rdl.Identifier) string { diff --git a/cmd/rdl-gen-parsec-java-model/main_test.go b/cmd/rdl-gen-parsec-java-model/main_test.go index 10cb747..e8adea7 100644 --- a/cmd/rdl-gen-parsec-java-model/main_test.go +++ b/cmd/rdl-gen-parsec-java-model/main_test.go @@ -1,6 +1,8 @@ package main import ( + "io/ioutil" + "os" "strings" "testing" @@ -223,3 +225,62 @@ func TestAppendAnnotation(t *testing.T) { gen.appendAnnotation("key", "value") assert.Equal(t, "key(value)", strings.Join(gen.body, "")) } + +func TestGenerateModelWithoutVersion(t *testing.T) { + testOutputDir := getTempDir(t, ".", "testOutput-") + path := testOutputDir + "/com/yahoo/shopping/parsec_generated/" + + //generate output result + schema, err := rdl.ParseRDLFile("../../testdata/sampleWithoutVersion.rdl", false, false, false) + if err != nil { + t.Fatalf("%v", err) + } + GenerateJavaModel("withoutVersion", schema, testOutputDir, true, "", false, "upper_first") + + //asserts + content := checkAndGetFileContent(t, path, "User.java") + assert.Contains(t, string(content), "class User") + + // clean up folder + defer os.RemoveAll(testOutputDir) +} + +func TestGenerateModelWithVersion(t *testing.T) { + testOutputDir := getTempDir(t, ".", "testOutput-") + path := testOutputDir + "/com/yahoo/shopping/parsec_generated/" + + //generate output result + schema, err := rdl.ParseRDLFile("../../testdata/sampleWithVersion.rdl", false, false, false) + if err != nil { + t.Fatalf("%v", err) + } + GenerateJavaModel("withVersion", schema, testOutputDir, true, "", false, "upper_first") + + //asserts + content := checkAndGetFileContent(t, path, "UserV2.java") + assert.Contains(t, string(content), "class UserV2") + + // clean up folder + defer os.RemoveAll(testOutputDir) +} + +func checkAndGetFileContent(t *testing.T, path string, fileName string) []byte { + //1. check correspanding client file exists + if _, err := os.Stat(path + fileName); err != nil { + t.Fatalf("file not exists: %s", path+fileName) + } + //2. check file content + content, err := os.ReadFile(path + fileName) + if err != nil { + t.Fatalf("can not read file: %s", path+fileName) + } + return content +} + +func getTempDir(t *testing.T, dir string, prefix string) string { + dir, err := ioutil.TempDir(dir, prefix) + if err != nil { + t.Fatalf("%v", err) + } + return dir +} diff --git a/cmd/rdl-gen-parsec-java-server/genServerTemplate_test.go b/cmd/rdl-gen-parsec-java-server/genServerTemplate_test.go new file mode 100644 index 0000000..29c4089 --- /dev/null +++ b/cmd/rdl-gen-parsec-java-server/genServerTemplate_test.go @@ -0,0 +1,108 @@ +package main + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/ardielle/ardielle-go/rdl" + "github.com/stretchr/testify/assert" +) + +func TestGenerateServerWithoutVersion(t *testing.T) { + testOutputDir := getTempDir(t, ".", "testOutput-") + path := testOutputDir + "/com/yahoo/shopping/parsec_generated/" + srcPath := "./src/main/java/com/yahoo/shopping/" + + //generate output result + schema, err := rdl.ParseRDLFile("../../testdata/sampleWithoutVersion.rdl", false, false, false) + if err != nil { + t.Fatalf("%v", err) + } + GenerateJavaServer("withoutVersion", schema, testOutputDir, true, true, true, true, string(schema.Namespace), false) + + //asserts + resourcesContent := checkAndGetFileContent(t, path, "SampleResources.java") + assert.Contains(t, string(resourcesContent), "class SampleResources") + assert.Contains(t, string(resourcesContent), "@Path(\"/sample\")") + assert.Contains(t, string(resourcesContent), "User user") + + handlerContent := checkAndGetFileContent(t, path, "SampleHandler.java") + assert.Contains(t, string(handlerContent), "interface SampleHandler") + assert.Contains(t, string(handlerContent), "public User postUsers(ResourceContext context, User user)") + assert.Contains(t, string(handlerContent), "public User getUsersById(ResourceContext context, Integer id)") + + serverContent := checkAndGetFileContent(t, path, "SampleServer.java") + assert.Contains(t, string(serverContent), "class SampleServer") + assert.Contains(t, string(serverContent), "bind(handler).to(SampleHandler.class)") + + hImplContent := checkAndGetFileContent(t, srcPath, "SampleHandlerImpl.java") + assert.Contains(t, string(hImplContent), "class SampleHandlerImpl") + assert.Contains(t, string(hImplContent), "implements SampleHandler") + assert.Contains(t, string(hImplContent), "public User postUsers(ResourceContext context, User user)") + assert.Contains(t, string(hImplContent), "public User getUsersById(ResourceContext context, Integer id)") + + // clean up folder + defer os.RemoveAll(testOutputDir) + defer os.RemoveAll("./src") +} + +func TestGenerateServerWithVersion(t *testing.T) { + testOutputDir := getTempDir(t, ".", "testOutput-") + path := testOutputDir + "/com/yahoo/shopping/parsec_generated/" + srcPath := "./src/main/java/com/yahoo/shopping/" + + //generate output result + schema, err := rdl.ParseRDLFile("../../testdata/sampleWithVersion.rdl", false, false, false) + if err != nil { + t.Fatalf("%v", err) + } + + GenerateJavaServer("withVersion", schema, testOutputDir, true, true, true, true, string(schema.Namespace), false) + + //asserts + resourcesContent := checkAndGetFileContent(t, path, "SampleV2Resources.java") + assert.Contains(t, string(resourcesContent), "class SampleV2Resources") + assert.Contains(t, string(resourcesContent), "@Path(\"/sample/v2\")") + assert.Contains(t, string(resourcesContent), "UserV2 user") + + handlerContent := checkAndGetFileContent(t, path, "SampleV2Handler.java") + assert.Contains(t, string(handlerContent), "interface SampleV2Handler") + assert.Contains(t, string(handlerContent), "public UserV2 postUsers(ResourceContext context, UserV2 user)") + assert.Contains(t, string(handlerContent), "public UserV2 getUsersById(ResourceContext context, Integer id)") + + serverContent := checkAndGetFileContent(t, path, "SampleV2Server.java") + assert.Contains(t, string(serverContent), "class SampleV2Server") + assert.Contains(t, string(serverContent), "bind(handler).to(SampleV2Handler.class)") + + hImplContent := checkAndGetFileContent(t, srcPath, "SampleV2HandlerImpl.java") + assert.Contains(t, string(hImplContent), "class SampleV2HandlerImpl") + assert.Contains(t, string(hImplContent), "implements SampleV2Handler") + assert.Contains(t, string(hImplContent), "public UserV2 postUsers(ResourceContext context, UserV2 user)") + assert.Contains(t, string(hImplContent), "public UserV2 getUsersById(ResourceContext context, Integer id)") + + // clean up folder + defer os.RemoveAll(testOutputDir) + defer os.RemoveAll("./src") +} + +func checkAndGetFileContent(t *testing.T, path string, fileName string) []byte { + //1. check correspanding client file exists + if _, err := os.Stat(path + fileName); err != nil { + t.Fatalf("file not exists: %s", path+fileName) + } + //2. check file content + content, err := os.ReadFile(path + fileName) + if err != nil { + t.Fatalf("can not read file: %s", path+fileName) + } + return content +} + +func getTempDir(t *testing.T, dir string, prefix string) string { + dir, err := ioutil.TempDir(dir, prefix) + if err != nil { + t.Fatalf("%v", err) + } + return dir +} diff --git a/cmd/rdl-gen-parsec-java-server/main.go b/cmd/rdl-gen-parsec-java-server/main.go index 1d80667..dbab6ed 100644 --- a/cmd/rdl-gen-parsec-java-server/main.go +++ b/cmd/rdl-gen-parsec-java-server/main.go @@ -112,7 +112,8 @@ func GenerateJavaServer(banner string, schema *rdl.Schema, outdir string, genAnn return err } cName := utils.Capitalize(string(schema.Name)) - ver := *schema.Version + ver, err := utils.GetSchemaVersionOrDefault(schema, 1) + checkErr(err) if ver > 1 { // if rdl version > 1, we append V{version} in class name cName += "V" + strconv.Itoa(int(ver)) } @@ -155,7 +156,8 @@ func GenerateJavaServer(banner string, schema *rdl.Schema, outdir string, genAnn gen = &javaServerGenerator{reg, schema, cName, out, nil, banner, genAnnotations, nil, genUsingPath, namespace, isPcSuffix} packageName := utils.JavaGenerationPackage(schema, namespace) - ver := *schema.Version + ver, err = utils.GetSchemaVersionOrDefault(schema, 1) + checkErr(err) // import user defined struct classes for _, t := range schema.Types { tName, tType, _ := rdl.TypeInfo(t) @@ -803,7 +805,9 @@ func (gen *javaServerGenerator) makeJavaTypeRef(reg rdl.TypeRegistry, t *rdl.Typ } func (gen *javaServerGenerator) javaType(reg rdl.TypeRegistry, rdlType rdl.TypeRef, optional bool, items rdl.TypeRef, keys rdl.TypeRef) string { - return utils.JavaType(reg, rdlType, optional, items, keys, gen.isPcSuffix, *gen.schema.Version) + ver, err := utils.GetSchemaVersionOrDefault(gen.schema, 1) + checkErr(err) + return utils.JavaType(reg, rdlType, optional, items, keys, gen.isPcSuffix, ver) } func (gen *javaServerGenerator) processTemplate(templateSource string) error { @@ -923,7 +927,9 @@ func (gen *javaServerGenerator) handlerBody(r *rdl.Resource) string { fargs = append(fargs, bodyName) } } - methName, _ := javaMethodName(gen.registry, r, gen.genUsingPath, gen.isPcSuffix, *gen.schema.Version) + ver, err := utils.GetSchemaVersionOrDefault(gen.schema, 1) + checkErr(err) + methName, _ := javaMethodName(gen.registry, r, gen.genUsingPath, gen.isPcSuffix, ver) sargs := "" if len(fargs) > 0 { sargs = ", " + strings.Join(fargs, ", ") @@ -1070,7 +1076,9 @@ func (gen *javaServerGenerator) handlerSignature(r *rdl.Resource) string { spec += " @Consumes(\"application/json;charset=utf-8\")\n" } } - methName, _ := javaMethodName(gen.registry, r, gen.genUsingPath, gen.isPcSuffix, *gen.schema.Version) + ver, err := utils.GetSchemaVersionOrDefault(gen.schema, 1) + checkErr(err) + methName, _ := javaMethodName(gen.registry, r, gen.genUsingPath, gen.isPcSuffix, ver) return spec + " public " + returnType + " " + methName + "(" + strings.Join(params, ", ") + "\n )" } @@ -1239,7 +1247,9 @@ func (gen *javaServerGenerator) serverMethodSignature(r *rdl.Resource) string { returnType := gen.javaType(reg, r.Type, false, "", "") //noContent := r.Expected == "NO_CONTENT" && r.Alternatives == nil //FIX: if nocontent, return nothing, have a void result, and don't "@Produces" anything - methName, params := javaMethodName(reg, r, gen.genUsingPath, gen.isPcSuffix, *gen.schema.Version) + ver, err := utils.GetSchemaVersionOrDefault(gen.schema, 1) + checkErr(err) + methName, params := javaMethodName(reg, r, gen.genUsingPath, gen.isPcSuffix, ver) sparams := "" if len(params) > 0 { sparams = ", " + strings.Join(params, ", ") diff --git a/testdata/sampleWithVersion.rdl b/testdata/sampleWithVersion.rdl new file mode 100644 index 0000000..8b19f69 --- /dev/null +++ b/testdata/sampleWithVersion.rdl @@ -0,0 +1,22 @@ +namespace com.yahoo.shopping; +name sample; +version 2; + +// define datatype +type User struct { + int32 id; + string name; +} + +// define endpoints +// create a new user +resource User POST "/users" { + User user; + expected CREATED; +} + +// get a user by id +resource User GET "/users/{id}" { + int32 id; + expected OK; +} diff --git a/testdata/sampleWithoutVersion.rdl b/testdata/sampleWithoutVersion.rdl new file mode 100644 index 0000000..18ecdf7 --- /dev/null +++ b/testdata/sampleWithoutVersion.rdl @@ -0,0 +1,21 @@ +namespace com.yahoo.shopping; +name sample; + +// define datatype +type User struct { + int32 id; + string name; +} + +// define endpoints +// create a new user +resource User POST "/users" { + User user; + expected CREATED; +} + +// get a user by id +resource User GET "/users/{id}" { + int32 id; + expected OK; +} diff --git a/utils/java-util.go b/utils/java-util.go index a49d9af..a928d57 100644 --- a/utils/java-util.go +++ b/utils/java-util.go @@ -435,3 +435,13 @@ func JavaType( return javaType } } + +func GetSchemaVersionOrDefault(schema *rdl.Schema, defaultVersion int32) (int32, error) { + if schema != nil { + if schema.Version != nil { + return *schema.Version, nil + } + return defaultVersion, nil + } + return 0, fmt.Errorf("schema is nil") +}