mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-11 09:07:00 +02:00
This pull request adds 3 functions (and corresponding tests): `testhelpers/response_validation.go`: - `ValidateResponse` - `ValidateResponseData` field_data.go: - `ValidateStrict` (has the "strict" validation logic) The functions are primarily meant to be used in tests to ensure that the responses are consistent with the defined response schema. An example of how the functions can be used in tests can be found in #18636. ### Background This PR is part of the ongoing work to add structured responses in Vault OpenAPI (VLT-234)
273 lines
5.8 KiB
Go
273 lines
5.8 KiB
Go
package schema
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hashicorp/vault/sdk/framework"
|
|
)
|
|
|
|
func TestValidateResponse(t *testing.T) {
|
|
cases := map[string]struct {
|
|
schema *framework.Response
|
|
response map[string]interface{}
|
|
strict bool
|
|
errorExpected bool
|
|
}{
|
|
"nil schema, nil response, strict": {
|
|
schema: nil,
|
|
response: nil,
|
|
strict: true,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"nil schema, nil response, not strict": {
|
|
schema: nil,
|
|
response: nil,
|
|
strict: false,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"nil schema, good response, strict": {
|
|
schema: nil,
|
|
response: map[string]interface{}{
|
|
"foo": "bar",
|
|
},
|
|
strict: true,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"nil schema, good response, not strict": {
|
|
schema: nil,
|
|
response: map[string]interface{}{
|
|
"foo": "bar",
|
|
},
|
|
strict: true,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"nil schema fields, good response, strict": {
|
|
schema: &framework.Response{},
|
|
response: map[string]interface{}{
|
|
"foo": "bar",
|
|
},
|
|
strict: true,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"nil schema fields, good response, not strict": {
|
|
schema: &framework.Response{},
|
|
response: map[string]interface{}{
|
|
"foo": "bar",
|
|
},
|
|
strict: true,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"string schema field, string response, strict": {
|
|
schema: &framework.Response{
|
|
Fields: map[string]*framework.FieldSchema{
|
|
"foo": {
|
|
Type: framework.TypeString,
|
|
},
|
|
},
|
|
},
|
|
response: map[string]interface{}{
|
|
"foo": "bar",
|
|
},
|
|
strict: true,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"string schema field, string response, not strict": {
|
|
schema: &framework.Response{
|
|
Fields: map[string]*framework.FieldSchema{
|
|
"foo": {
|
|
Type: framework.TypeString,
|
|
},
|
|
},
|
|
},
|
|
response: map[string]interface{}{
|
|
"foo": "bar",
|
|
},
|
|
strict: false,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"string schema not required field, empty response, strict": {
|
|
schema: &framework.Response{
|
|
Fields: map[string]*framework.FieldSchema{
|
|
"foo": {
|
|
Type: framework.TypeString,
|
|
Required: false,
|
|
},
|
|
},
|
|
},
|
|
response: map[string]interface{}{},
|
|
strict: true,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"string schema required field, empty response, strict": {
|
|
schema: &framework.Response{
|
|
Fields: map[string]*framework.FieldSchema{
|
|
"foo": {
|
|
Type: framework.TypeString,
|
|
Required: true,
|
|
},
|
|
},
|
|
},
|
|
response: map[string]interface{}{},
|
|
strict: true,
|
|
errorExpected: true,
|
|
},
|
|
|
|
"string schema required field, empty response, not strict": {
|
|
schema: &framework.Response{
|
|
Fields: map[string]*framework.FieldSchema{
|
|
"foo": {
|
|
Type: framework.TypeString,
|
|
Required: true,
|
|
},
|
|
},
|
|
},
|
|
response: map[string]interface{}{},
|
|
strict: false,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"string schema required field, nil response, strict": {
|
|
schema: &framework.Response{
|
|
Fields: map[string]*framework.FieldSchema{
|
|
"foo": {
|
|
Type: framework.TypeString,
|
|
Required: true,
|
|
},
|
|
},
|
|
},
|
|
response: nil,
|
|
strict: true,
|
|
errorExpected: true,
|
|
},
|
|
|
|
"string schema required field, nil response, not strict": {
|
|
schema: &framework.Response{
|
|
Fields: map[string]*framework.FieldSchema{
|
|
"foo": {
|
|
Type: framework.TypeString,
|
|
Required: true,
|
|
},
|
|
},
|
|
},
|
|
response: nil,
|
|
strict: false,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"empty schema, string response, strict": {
|
|
schema: &framework.Response{
|
|
Fields: map[string]*framework.FieldSchema{},
|
|
},
|
|
response: map[string]interface{}{
|
|
"foo": "bar",
|
|
},
|
|
strict: true,
|
|
errorExpected: true,
|
|
},
|
|
|
|
"empty schema, string response, not strict": {
|
|
schema: &framework.Response{
|
|
Fields: map[string]*framework.FieldSchema{},
|
|
},
|
|
response: map[string]interface{}{
|
|
"foo": "bar",
|
|
},
|
|
strict: false,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"time schema, string response, strict": {
|
|
schema: &framework.Response{
|
|
Fields: map[string]*framework.FieldSchema{
|
|
"time": {
|
|
Type: framework.TypeTime,
|
|
Required: true,
|
|
},
|
|
},
|
|
},
|
|
response: map[string]interface{}{
|
|
"time": "2024-12-11T09:08:07Z",
|
|
},
|
|
strict: true,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"time schema, string response, not strict": {
|
|
schema: &framework.Response{
|
|
Fields: map[string]*framework.FieldSchema{
|
|
"time": {
|
|
Type: framework.TypeTime,
|
|
Required: true,
|
|
},
|
|
},
|
|
},
|
|
response: map[string]interface{}{
|
|
"time": "2024-12-11T09:08:07Z",
|
|
},
|
|
strict: false,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"time schema, time response, strict": {
|
|
schema: &framework.Response{
|
|
Fields: map[string]*framework.FieldSchema{
|
|
"time": {
|
|
Type: framework.TypeTime,
|
|
Required: true,
|
|
},
|
|
},
|
|
},
|
|
response: map[string]interface{}{
|
|
"time": time.Date(2024, 12, 11, 9, 8, 7, 0, time.UTC),
|
|
},
|
|
strict: true,
|
|
errorExpected: false,
|
|
},
|
|
|
|
"time schema, time response, not strict": {
|
|
schema: &framework.Response{
|
|
Fields: map[string]*framework.FieldSchema{
|
|
"time": {
|
|
Type: framework.TypeTime,
|
|
Required: true,
|
|
},
|
|
},
|
|
},
|
|
response: map[string]interface{}{
|
|
"time": time.Date(2024, 12, 11, 9, 8, 7, 0, time.UTC),
|
|
},
|
|
strict: false,
|
|
errorExpected: false,
|
|
},
|
|
}
|
|
|
|
for name, tc := range cases {
|
|
name, tc := name, tc
|
|
t.Run(name, func(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
err := validateResponseDataImpl(
|
|
tc.schema,
|
|
tc.response,
|
|
tc.strict,
|
|
)
|
|
if err == nil && tc.errorExpected == true {
|
|
t.Fatalf("expected an error, got nil")
|
|
}
|
|
if err != nil && tc.errorExpected == false {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
})
|
|
}
|
|
}
|