-
Notifications
You must be signed in to change notification settings - Fork 277
fix(parameter): resolve ref for allOf #10558
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 4 commits
ff9994d
344529f
6cf507e
082a559
6cc7268
987dd8d
8841c79
2ab2a1f
44c502c
a554ba6
3199bcf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,88 +23,45 @@ import ( | |
| "bytes" | ||
| "encoding/json" | ||
| "os" | ||
| "reflect" | ||
| "testing" | ||
|
|
||
| "github.com/google/go-cmp/cmp" | ||
| . "github.com/onsi/ginkgo/v2" | ||
| . "github.com/onsi/gomega" | ||
|
|
||
| "github.com/apecloud/kubeblocks/pkg/parameters/core" | ||
| "github.com/apecloud/kubeblocks/test/testdata" | ||
| ) | ||
|
|
||
| func TestGenerateOpenApiSchema(t *testing.T) { | ||
| type args struct { | ||
| cueFile string | ||
| schemaType string | ||
| } | ||
| tests := []struct { | ||
| name string | ||
| args args | ||
| want string | ||
| wantErr bool | ||
| }{{ | ||
| name: "normal_test", | ||
| args: args{ | ||
| cueFile: "test_import_type.cue", | ||
| schemaType: "Exemplar", | ||
| }, | ||
| want: "test_import_type.json", | ||
| wantErr: false, | ||
| }, { | ||
| name: "normal_test", | ||
| args: args{ | ||
| cueFile: "mysql_openapi.cue", | ||
| schemaType: "MysqlParameter", | ||
| }, | ||
| want: "mysql_openapi.json", | ||
| wantErr: false, | ||
| }, { | ||
| // name: "normal_test", | ||
| // args: args{ | ||
| // cueFile: "mysql_openapi_v2.cue", | ||
| // schemaType: "MysqlSchema", | ||
| // }, | ||
| // want: "mysql_openapi_v2.json", | ||
| // wantErr: false, | ||
| // }, { | ||
| name: "normal_with_not_empty", | ||
| args: args{ | ||
| cueFile: "mysql_openapi.cue", | ||
| schemaType: "", | ||
| }, | ||
| want: "mysql_openapi.json", | ||
| wantErr: false, | ||
| }, { | ||
| name: "pg14_openapi", | ||
| args: args{ | ||
| cueFile: "pg14.cue", | ||
| schemaType: "PGPameter", | ||
| }, | ||
| want: "pg14_openapi.json", | ||
| wantErr: false, | ||
| }, { | ||
| name: "failed_test", | ||
| args: args{ | ||
| cueFile: "mysql.cue", | ||
| schemaType: "NotType", | ||
| }, | ||
| want: "mysql_openapi_failed_not_exist", | ||
| wantErr: true, | ||
| }} | ||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| got, err := runOpenAPITest(tt.args.cueFile, tt.args.schemaType) | ||
| if (err != nil) != tt.wantErr { | ||
| t.Errorf("GenerateOpenAPISchema() error = %v, wantErr %v", err, tt.wantErr) | ||
| RegisterFailHandler(Fail) | ||
| RunSpecs(t, "OpenAPI Schema Suite") | ||
| } | ||
|
|
||
| var _ = Describe("GenerateOpenAPISchema", func() { | ||
| DescribeTable("generates schema from CUE definitions", | ||
| func(cueFile, schemaType, want string, wantErr bool) { | ||
| got, err := runOpenAPITest(cueFile, schemaType) | ||
| GinkgoWriter.Println(string(got)) | ||
| Expect(err != nil).To(Equal(wantErr), "GenerateOpenAPISchema() error = %v, wantErr %v", err, wantErr) | ||
| if wantErr { | ||
| return | ||
| } | ||
| wantContent := getContentFromFile(tt.want) | ||
| if !reflect.DeepEqual(got, wantContent) { | ||
| t.Errorf("GenerateOpenAPISchema() diff: %s", cmp.Diff(wantContent, got)) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
|
|
||
| wantContent := getContentFromFile(want) | ||
| Expect(got).To(Equal(wantContent), "GenerateOpenAPISchema() diff: %s", cmp.Diff(wantContent, got)) | ||
| }, | ||
| Entry("test_import_type", "test_import_type.cue", "Exemplar", "test_import_type.json", false), | ||
| Entry("normal_test with mysql", "mysql_openapi.cue", "MysqlParameter", "mysql_openapi.json", false), | ||
| Entry("normal_test with mysql2", "mysql_openapi_v2.cue", "MysqlSchema", "mysql_openapi_v2.json", false), | ||
| Entry("normal_with_not_empty", "mysql_openapi.cue", "", "mysql_openapi.json", false), | ||
| Entry("pg14_openapi", "pg14.cue", "PGPameter", "pg14_openapi.json", false), | ||
| Entry("multiple_schema_arch_a", "multiple_schema.cue", "archA", "multiple_schema_arch_a.json", false), | ||
| Entry("multiple_schema_combined", "multiple_schema.cue", "combined", "multiple_schema_combined.json", false), | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [P2] These new cases only combine disjoint optional string properties and compare the serialized golden shape, so they cannot detect the semantic loss introduced by |
||
| Entry("multiple_schema_embedded", "multiple_schema.cue", "embedded", "multiple_schema_combined.json", false), | ||
| Entry("failed_test", "mysql.cue", "NotType", "mysql_openapi_failed_not_exist", true), | ||
| ) | ||
| }) | ||
|
|
||
| func getContentFromFile(file string) []byte { | ||
| content, err := os.ReadFile(testdata.SubTestDataPath("./cue_testdata/" + file)) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| // Copyright (C) 2022-2026 ApeCloud Co., Ltd | ||
| // | ||
| // This file is part of KubeBlocks project | ||
| // | ||
| // This program is free software: you can redistribute it and/or modify | ||
| // it under the terms of the GNU Affero General Public License as published by | ||
| // the Free Software Foundation, either version 3 of the License, or | ||
| // (at your option) any later version. | ||
| // | ||
| // This program is distributed in the hope that it will be useful | ||
| // but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| // GNU Affero General Public License for more details. | ||
| // | ||
| // You should have received a copy of the GNU Affero General Public License | ||
| // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
|
||
| #shared: { | ||
| a?: string | ||
| } | ||
|
|
||
| #archA: #shared & { | ||
| b?: string | ||
| } | ||
|
|
||
| #archB: #shared & { | ||
| c?: string | ||
| } | ||
|
|
||
| #combined: #archA & #archB | ||
|
|
||
| #embedded: { | ||
| #archA | ||
| #archB | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| { | ||
| "type": "object", | ||
| "properties": { | ||
| "spec": { | ||
| "type": "object", | ||
| "properties": { | ||
| "a": { | ||
| "type": "string" | ||
| }, | ||
| "b": { | ||
| "type": "string" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| { | ||
| "type": "object", | ||
| "properties": { | ||
| "spec": { | ||
| "type": "object", | ||
| "properties": { | ||
| "a": { | ||
| "type": "string" | ||
| }, | ||
| "b": { | ||
| "type": "string" | ||
| }, | ||
| "c": { | ||
| "type": "string" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P1] This is a lossy approximation of
allOf, not an equivalent expansion.allOfrequires every branch to apply simultaneously, but duplicate properties are handled as first-wins here, so constraints from later branches are silently discarded. The same loss occurs for object-level keywords becausemergeSchemaPropscopies onlytype,properties,additionalProperties, andrequired; fields such asdescription,maxProperties,oneOf, andnotdisappear. A CUE field whose lower and upper bounds come from separate branches therefore keeps only one bound in the generated schema and can accept a value rejected by CUE. Since this result is exposed asSchemaInJSON, this changes the API semantics and is a blocker.