2023-03-15 16:00:52 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2023-01-13 19:55:56 +00:00
|
|
|
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,
|
|
|
|
},
|
2023-03-14 17:21:20 +00:00
|
|
|
|
|
|
|
"empty schema, response has http_raw_body, strict": {
|
|
|
|
schema: &framework.Response{
|
|
|
|
Fields: map[string]*framework.FieldSchema{},
|
|
|
|
},
|
|
|
|
response: map[string]interface{}{
|
|
|
|
"http_raw_body": "foo",
|
|
|
|
},
|
|
|
|
strict: true,
|
|
|
|
errorExpected: false,
|
|
|
|
},
|
|
|
|
|
|
|
|
"empty schema, response has http_raw_body, not strict": {
|
|
|
|
schema: &framework.Response{
|
|
|
|
Fields: map[string]*framework.FieldSchema{},
|
|
|
|
},
|
|
|
|
response: map[string]interface{}{
|
|
|
|
"http_raw_body": "foo",
|
|
|
|
},
|
|
|
|
strict: false,
|
|
|
|
errorExpected: false,
|
|
|
|
},
|
|
|
|
|
2023-03-23 20:33:44 +00:00
|
|
|
"string schema field, response has non-200 http_status_code, strict": {
|
|
|
|
schema: &framework.Response{
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"foo": {
|
|
|
|
Type: framework.TypeString,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
response: map[string]interface{}{
|
|
|
|
"http_status_code": 304,
|
|
|
|
},
|
|
|
|
strict: true,
|
|
|
|
errorExpected: false,
|
|
|
|
},
|
|
|
|
|
|
|
|
"string schema field, response has non-200 http_status_code, not strict": {
|
|
|
|
schema: &framework.Response{
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"foo": {
|
|
|
|
Type: framework.TypeString,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
response: map[string]interface{}{
|
|
|
|
"http_status_code": 304,
|
|
|
|
},
|
|
|
|
strict: false,
|
|
|
|
errorExpected: false,
|
|
|
|
},
|
|
|
|
|
2023-03-14 17:21:20 +00:00
|
|
|
"schema has http_raw_body, strict": {
|
|
|
|
schema: &framework.Response{
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"http_raw_body": {
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Required: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
response: map[string]interface{}{
|
|
|
|
"http_raw_body": "foo",
|
|
|
|
},
|
|
|
|
strict: true,
|
|
|
|
errorExpected: true,
|
|
|
|
},
|
|
|
|
|
|
|
|
"schema has http_raw_body, not strict": {
|
|
|
|
schema: &framework.Response{
|
|
|
|
Fields: map[string]*framework.FieldSchema{
|
|
|
|
"http_raw_body": {
|
|
|
|
Type: framework.TypeString,
|
|
|
|
Required: false,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
response: map[string]interface{}{
|
|
|
|
"http_raw_body": "foo",
|
|
|
|
},
|
|
|
|
strict: false,
|
|
|
|
errorExpected: true,
|
|
|
|
},
|
2023-01-13 19:55:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|