private List<ValidationEvent> validateShape(
            Model model,
            OperationIndex operationIndex,
            Shape shape,
            T trait
    ) {
        List<ValidationEvent> events = new ArrayList<>();
        List<? extends HttpMessageTestCase> testCases = getTestCases(trait);

        for (int i = 0; i < testCases.size(); i++) {
            HttpMessageTestCase testCase = testCases.get(i);

            // Validate the syntax of known media types like XML and JSON.
            events.addAll(validateMediaType(shape, trait, testCase));

            // Validate the vendorParams for the test case if we have a shape defined.
            Optional<ShapeId> vendorParamsShapeOptional = testCase.getVendorParamsShape();
            ObjectNode vendorParams = testCase.getVendorParams();
            if (vendorParamsShapeOptional.isPresent() && isValidatedBy(shape)) {
                if (vendorParams.isEmpty()) {
                    // Warn if vendorParamsShape is set on the case and no vendorParams is set.
                    events.add(warning(shape,
                            trait,
                            "Protocol test case defined a `vendorParamsShape` but no `vendorParams`"));
                } else {
                    // Otherwise, validate the params against the shape.
                    Shape vendorParamsShape = model.expectShape(vendorParamsShapeOptional.get());
                    NodeValidationVisitor vendorParamsValidator = createVisitor(vendorParams,
                            model,
                            shape,
                            i,
                            ".vendorParams");
                    events.addAll(vendorParamsShape.accept(vendorParamsValidator));
                }
            }

            StructureShape struct = getStructure(shape, operationIndex);
            if (struct != null) {
                // Validate the params for the test case.
                NodeValidationVisitor validator = createVisitor(testCase.getParams(), model, shape, i, ".params");
                events.addAll(struct.accept(validator));
            } else if (!testCase.getParams().isEmpty() && isValidatedBy(shape)) {
                events.add(error(shape,
                        trait,
                        String.format(
                                "Protocol test %s parameters provided for operation with no %s: `%s`",
                                descriptor,
                                descriptor,
                                Node.printJson(testCase.getParams()))));
            }
        }

        return events;
    }
Validates the following:

<ul>
    <li>XML and JSON bodyMediaTypes contain valid content.</li>
    <li>vendorParamsShape is a valid shape.</li>
    <li>Vendor params are compatible with any referenced shape.</li>
    <li>Params for a test case are valid for the model.</li>
</ul>

@param <T> Type of test case to validate.
smithy-protocol-test-traits/src/main/java/software/amazon/smithy/protocoltests/traits/ProtocolTestCaseValidator.java