vault/sdk/helper/testhelpers/schema/response_validation_test.go
Anton Averchenkov 6a2586747c
Add response schema validation methods & test helpers (#18635)
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)
2023-01-13 14:55:56 -05:00

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)
}
})
}
}