This is an automated email from the ASF dual-hosted git repository.

Alanxtl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go.git


The following commit(s) were added to refs/heads/develop by this push:
     new 5f9deabac test(openAPI): add golden tests for 
protoc-gen-triple-openapi (#3606)
5f9deabac is described below

commit 5f9deabac98261c389a29ae8cde6b67d4205a29c
Author: XiaoFei <[email protected]>
AuthorDate: Fri Aug 7 10:40:05 2026 +0800

    test(openAPI): add golden tests for protoc-gen-triple-openapi (#3606)
    
    * test(openAPI): add golden tests for protoc-gen-triple-openapi
    
    * fix(openapi): normalize golden test line endings
---
 .../protoc-gen-triple-openapi/example/greet.proto  |  13 ++
 .../example/greet.triple.openapi.json              |  43 +++++
 .../example/greet.triple.openapi.yaml              |  31 ++++
 .../internal/converter/convert_test.go             | 188 +++++++++++++++++++++
 4 files changed, 275 insertions(+)

diff --git a/tools/protoc-gen-triple-openapi/example/greet.proto 
b/tools/protoc-gen-triple-openapi/example/greet.proto
index c31829c3f..3db26d2d7 100644
--- a/tools/protoc-gen-triple-openapi/example/greet.proto
+++ b/tools/protoc-gen-triple-openapi/example/greet.proto
@@ -21,8 +21,21 @@ package greet;
 
 option go_package = 
"dubbo.apache.org/dubbo-go/v3/tools/protoc-gen-triple-openapi/example;greet";
 
+enum GreetingType {
+  GREETING_TYPE_UNSPECIFIED = 0;
+  GREETING_TYPE_FORMAL = 1;
+}
+
 message GreetRequest {
   string name = 1;
+  repeated string aliases = 2;
+  map<string, string> metadata = 3;
+  GreetingType type = 4;
+  GreetProfile profile = 5;
+}
+
+message GreetProfile {
+  string salutation = 1;
 }
 
 message GreetResponse {
diff --git a/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.json 
b/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.json
index b0f578fe3..8a322723f 100644
--- a/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.json
+++ b/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.json
@@ -115,16 +115,59 @@
   },
   "components": {
     "schemas": {
+      "greet.GreetProfile": {
+        "type": "object",
+        "properties": {
+          "salutation": {
+            "type": "string",
+            "title": "salutation"
+          }
+        },
+        "title": "GreetProfile"
+      },
       "greet.GreetRequest": {
         "type": "object",
         "properties": {
           "name": {
             "type": "string",
             "title": "name"
+          },
+          "aliases": {
+            "type": "array",
+            "items": {
+              "type": "string"
+            },
+            "title": "aliases"
+          },
+          "metadata": {
+            "type": "object",
+            "title": "metadata"
+          },
+          "type": {
+            "title": "type",
+            "$ref": "#/components/schemas/greet.GreetingType"
+          },
+          "profile": {
+            "title": "profile",
+            "$ref": "#/components/schemas/greet.GreetProfile"
           }
         },
         "title": "GreetRequest"
       },
+      "greet.GreetRequest.MetadataEntry": {
+        "type": "object",
+        "properties": {
+          "key": {
+            "type": "string",
+            "title": "key"
+          },
+          "value": {
+            "type": "string",
+            "title": "value"
+          }
+        },
+        "title": "MetadataEntry"
+      },
       "greet.GreetResponse": {
         "type": "object",
         "properties": {
diff --git a/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.yaml 
b/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.yaml
index 7f6f7979d..a56c7ccb9 100644
--- a/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.yaml
+++ b/tools/protoc-gen-triple-openapi/example/greet.triple.openapi.yaml
@@ -69,13 +69,44 @@ paths:
                 $ref: '#/components/schemas/ErrorResponse'
 components:
   schemas:
+    greet.GreetProfile:
+      type: object
+      properties:
+        salutation:
+          type: string
+          title: salutation
+      title: GreetProfile
     greet.GreetRequest:
       type: object
       properties:
         name:
           type: string
           title: name
+        aliases:
+          type: array
+          items:
+            type: string
+          title: aliases
+        metadata:
+          type: object
+          title: metadata
+        type:
+          title: type
+          $ref: '#/components/schemas/greet.GreetingType'
+        profile:
+          title: profile
+          $ref: '#/components/schemas/greet.GreetProfile'
       title: GreetRequest
+    greet.GreetRequest.MetadataEntry:
+      type: object
+      properties:
+        key:
+          type: string
+          title: key
+        value:
+          type: string
+          title: value
+      title: MetadataEntry
     greet.GreetResponse:
       type: object
       properties:
diff --git a/tools/protoc-gen-triple-openapi/internal/converter/convert_test.go 
b/tools/protoc-gen-triple-openapi/internal/converter/convert_test.go
new file mode 100644
index 000000000..2278ac1f9
--- /dev/null
+++ b/tools/protoc-gen-triple-openapi/internal/converter/convert_test.go
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package converter
+
+import (
+       "flag"
+       "os"
+       "path/filepath"
+       "runtime"
+       "strings"
+       "testing"
+)
+
+import (
+       "google.golang.org/protobuf/proto"
+
+       "google.golang.org/protobuf/types/descriptorpb"
+       "google.golang.org/protobuf/types/pluginpb"
+)
+
+var updateGolden = flag.Bool("update", false, "update OpenAPI golden files")
+
+func TestConvertGolden(t *testing.T) {
+       tests := []struct {
+               name       string
+               format     string
+               goldenFile string
+       }{
+               {
+                       name:       "YAML",
+                       format:     "yaml",
+                       goldenFile: "greet.triple.openapi.yaml",
+               },
+               {
+                       name:       "JSON",
+                       format:     "json",
+                       goldenFile: "greet.triple.openapi.json",
+               },
+       }
+
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       response, err := convert(greetRequest(tt.format))
+                       if err != nil {
+                               t.Fatalf("convert() error = %v", err)
+                       }
+                       if len(response.File) != 1 {
+                               t.Fatalf("generated %d files, want 1", 
len(response.File))
+                       }
+
+                       got := response.File[0].GetContent()
+                       goldenPath := examplePath(t, tt.goldenFile)
+                       if *updateGolden {
+                               if err := os.WriteFile(goldenPath, []byte(got), 
0o644); err != nil {
+                                       t.Fatalf("update golden file: %v", err)
+                               }
+                               return
+                       }
+
+                       want, err := os.ReadFile(goldenPath)
+                       if err != nil {
+                               t.Fatalf("read golden file: %v", err)
+                       }
+                       got = strings.ReplaceAll(got, "\r\n", "\n")
+                       wantText := strings.ReplaceAll(string(want), "\r\n", 
"\n")
+                       if got != wantText {
+                               t.Errorf("generated OpenAPI differs from 
%s\n--- want\n%s\n--- got\n%s", tt.goldenFile, wantText, got)
+                       }
+               })
+       }
+}
+
+func examplePath(t *testing.T, name string) string {
+       t.Helper()
+       _, sourceFile, _, ok := runtime.Caller(0)
+       if !ok {
+               t.Fatal("locate test source file")
+       }
+       return filepath.Join(filepath.Dir(sourceFile), "..", "..", "example", 
name)
+}
+
+func greetRequest(format string) *pluginpb.CodeGeneratorRequest {
+       const fileName = "example/greet.proto"
+       return &pluginpb.CodeGeneratorRequest{
+               FileToGenerate: []string{fileName},
+               Parameter:      proto.String("format=" + format),
+               ProtoFile: []*descriptorpb.FileDescriptorProto{
+                       {
+                               Name:    proto.String(fileName),
+                               Package: proto.String("greet"),
+                               Syntax:  proto.String("proto3"),
+                               EnumType: []*descriptorpb.EnumDescriptorProto{
+                                       {
+                                               Name: 
proto.String("GreetingType"),
+                                               Value: 
[]*descriptorpb.EnumValueDescriptorProto{
+                                                       {Name: 
proto.String("GREETING_TYPE_UNSPECIFIED"), Number: proto.Int32(0)},
+                                                       {Name: 
proto.String("GREETING_TYPE_FORMAL"), Number: proto.Int32(1)},
+                                               },
+                                       },
+                               },
+                               MessageType: []*descriptorpb.DescriptorProto{
+                                       {
+                                               Name: 
proto.String("GreetRequest"),
+                                               Field: 
[]*descriptorpb.FieldDescriptorProto{
+                                                       field("name", "name", 
1, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_STRING, ""),
+                                                       field("aliases", 
"aliases", 2, descriptorpb.FieldDescriptorProto_LABEL_REPEATED, 
descriptorpb.FieldDescriptorProto_TYPE_STRING, ""),
+                                                       field("metadata", 
"metadata", 3, descriptorpb.FieldDescriptorProto_LABEL_REPEATED, 
descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, 
".greet.GreetRequest.MetadataEntry"),
+                                                       field("type", "type", 
4, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_ENUM, ".greet.GreetingType"),
+                                                       field("profile", 
"profile", 5, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_MESSAGE, ".greet.GreetProfile"),
+                                               },
+                                               NestedType: 
[]*descriptorpb.DescriptorProto{
+                                                       {
+                                                               Name: 
proto.String("MetadataEntry"),
+                                                               Field: 
[]*descriptorpb.FieldDescriptorProto{
+                                                                       
field("key", "key", 1, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_STRING, ""),
+                                                                       
field("value", "value", 2, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_STRING, ""),
+                                                               },
+                                                               Options: 
&descriptorpb.MessageOptions{MapEntry: proto.Bool(true)},
+                                                       },
+                                               },
+                                       },
+                                       {
+                                               Name: 
proto.String("GreetProfile"),
+                                               Field: 
[]*descriptorpb.FieldDescriptorProto{
+                                                       field("salutation", 
"salutation", 1, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_STRING, ""),
+                                               },
+                                       },
+                                       {
+                                               Name: 
proto.String("GreetResponse"),
+                                               Field: 
[]*descriptorpb.FieldDescriptorProto{
+                                                       field("greeting", 
"greeting", 1, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_STRING, ""),
+                                               },
+                                       },
+                                       {
+                                               Name: 
proto.String("GreetUserRequest"),
+                                               Field: 
[]*descriptorpb.FieldDescriptorProto{
+                                                       field("name", "name", 
1, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_STRING, ""),
+                                               },
+                                       },
+                                       {
+                                               Name: 
proto.String("GreetUserResponse"),
+                                               Field: 
[]*descriptorpb.FieldDescriptorProto{
+                                                       field("greeting", 
"greeting", 1, descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL, 
descriptorpb.FieldDescriptorProto_TYPE_STRING, ""),
+                                               },
+                                       },
+                               },
+                               Service: []*descriptorpb.ServiceDescriptorProto{
+                                       {
+                                               Name: 
proto.String("GreetService"),
+                                               Method: 
[]*descriptorpb.MethodDescriptorProto{
+                                                       {Name: 
proto.String("Greet"), InputType: proto.String(".greet.GreetRequest"), 
OutputType: proto.String(".greet.GreetResponse")},
+                                                       {Name: 
proto.String("GreetUser"), InputType: proto.String(".greet.GreetUserRequest"), 
OutputType: proto.String(".greet.GreetUserResponse")},
+                                               },
+                                       },
+                               },
+                       },
+               },
+       }
+}
+
+func field(name, jsonName string, number int32, label 
descriptorpb.FieldDescriptorProto_Label, kind 
descriptorpb.FieldDescriptorProto_Type, typeName string) 
*descriptorpb.FieldDescriptorProto {
+       fd := &descriptorpb.FieldDescriptorProto{
+               Name:     proto.String(name),
+               JsonName: proto.String(jsonName),
+               Number:   proto.Int32(number),
+               Label:    label.Enum(),
+               Type:     kind.Enum(),
+       }
+       if typeName != "" {
+               fd.TypeName = proto.String(typeName)
+       }
+       return fd
+}

Reply via email to