Skip to content

Commit

Permalink
Add tests for the other kinds of schema (#22)
Browse files Browse the repository at this point in the history
This tests to make sure that the `additionalProperties: false` and `--nullable-all` schemas validate different sets of values to to the ones that are validated by the default `schema.json`.

In particular, `schema-nullable-all.json` should (unless disallowed by certain fields such as `enum`) all a file with all variables defined as `null`.  `schema-disallow-additional.json` should disallow additional properties, including within nested objects.
  • Loading branch information
AislingHPE authored Aug 30, 2024
1 parent 3995cff commit 5560763
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 5 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ running Terraform.
- `--stdout`: Print schema to stdout and prevent all other logging unless an error occurs. Does not create a file.
Overrides `--debug` and `--output`.

- `--export-variables`: Export the variables in JSON format directly and do not create a JSON Schema. This provides similar functionality to applications such as terraform-docs, where the input variables can be output to a machine-readable format such as JSON. The `type` field is converted to a type constraint based on the type definition, and the `default` field is translated to its literal value. `condition` inside the `validation` block is left as a string, because it is difficult to represent arbitrary (ie unevaluated) hcl Expressions in JSON.
- `--export-variables`: Export the variables in JSON format directly and do not create a JSON Schema. This provides similar functionality to applications such as terraform-docs, where the input variables can be output to a machine-readable format such as JSON. The `type` field is converted to a type constraint based on the type definition, and the `default` field is translated to its literal value. `condition` inside the `validation` block is left as a string, because it is difficult to represent arbitrary (ie unevaluated) HCL Expressions in JSON.

- `--escape-json`: Escape special characters in the JSON (`<`,`>` and `&`) so that the schema can be used in a web context. By default, this behaviour is disabled so the JSON file can be read more easily, though it does not effect external programs such as `jq`.

Expand Down
130 changes: 130 additions & 0 deletions pkg/jsonschema/json-schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ func getErrorLocationsFromValidationErr(t *testing.T, valErr *jsonschema.Validat
return keywordLocations
}

//nolint:funlen,maintidx
func TestSampleInput(t *testing.T) {
t.Parallel()

Expand All @@ -95,6 +96,7 @@ func TestSampleInput(t *testing.T) {
filePath string
keywordLocations []errorLocation
}{
// Minimum input
{
name: "empty minimum input",
filePath: "../../test/expected/empty/sample-input/test-input-min.json",
Expand Down Expand Up @@ -125,6 +127,7 @@ func TestSampleInput(t *testing.T) {
schemaPath: "../../test/expected/custom-validation/schema.json",
keywordLocations: nil,
},
// Maximum input plus an unknown variable, additionalProperties is true
{
name: "simple full input",
filePath: "../../test/expected/simple/sample-input/test-input-all.json",
Expand All @@ -149,6 +152,41 @@ func TestSampleInput(t *testing.T) {
schemaPath: "../../test/expected/custom-validation/schema.json",
keywordLocations: nil,
},
// Maximum input plus an unknown variable, additionalProperties is false
{
name: "simple full input additionalProperties false",
filePath: "../../test/expected/simple/sample-input/test-input-all.json",
schemaPath: "../../test/expected/simple/schema-disallow-additional.json",
keywordLocations: []errorLocation{
{name: "/additionalProperties"},
},
},
{
name: "simple-types full input additionalProperties false",
filePath: "../../test/expected/simple-types/sample-input/test-input-all.json",
schemaPath: "../../test/expected/simple-types/schema-disallow-additional.json",
keywordLocations: []errorLocation{
{name: "/additionalProperties"},
},
},
{
name: "complex-types full input additionalProperties false",
filePath: "../../test/expected/complex-types/sample-input/test-input-all.json",
schemaPath: "../../test/expected/complex-types/schema-disallow-additional.json",
keywordLocations: []errorLocation{
{name: "/additionalProperties"},
},
},
{
name: "custom-validation full input additionalProperties false",
filePath: "../../test/expected/custom-validation/sample-input/test-input-all.json",
schemaPath: "../../test/expected/custom-validation/schema-disallow-additional.json",
keywordLocations: []errorLocation{
{name: "/additionalProperties"},
{name: "/properties/an_object_maximum_minimum_items/additionalProperties"},
},
},
// bad input on all fields
{
name: "simple bad input",
filePath: "../../test/expected/simple/sample-input/test-input-bad.json",
Expand Down Expand Up @@ -271,6 +309,98 @@ func TestSampleInput(t *testing.T) {
},
},
},
// null input on all fields, nullableAll is false
{
name: "simple null input nullableAll false",
filePath: "../../test/expected/simple/sample-input/test-input-null.json",
schemaPath: "../../test/expected/simple/schema.json",
keywordLocations: []errorLocation{
{name: "/properties/age/type"},
{name: "/properties/name/type"},
},
},
{
name: "simple-types null input nullableAll false",
filePath: "../../test/expected/simple-types/sample-input/test-input-null.json",
schemaPath: "../../test/expected/simple-types/schema.json",
keywordLocations: []errorLocation{
{name: "/properties/a_bool/type"},
{name: "/properties/a_list/type"},
{name: "/properties/a_map_of_strings/type"},
{name: "/properties/a_number/type"},
{name: "/properties/a_set/type"},
{name: "/properties/a_string/type"},
{name: "/properties/a_tuple/type"},
{name: "/properties/a_variable_in_another_file/type"},
{name: "/properties/an_object/type"},
},
},
{
name: "complex-types null input nullableAll false",
filePath: "../../test/expected/complex-types/sample-input/test-input-null.json",
schemaPath: "../../test/expected/complex-types/schema.json",
keywordLocations: []errorLocation{
{name: "/properties/a_very_complicated_object/type"},
{name: "/properties/an_object_with_optional/type"},
},
},
{
name: "custom-validation null input nullableAll false",
filePath: "../../test/expected/custom-validation/sample-input/test-input-null.json",
schemaPath: "../../test/expected/custom-validation/schema.json",
keywordLocations: []errorLocation{
{name: "/properties/a_list_maximum_minimum_length/type"},
{name: "/properties/a_map_maximum_minimum_entries/type"},
{name: "/properties/a_number_enum_kind_1/type"},
{name: "/properties/a_number_enum_kind_2/type"},
{name: "/properties/a_number_exclusive_maximum_minimum/type"},
{name: "/properties/a_number_maximum_minimum/type"},
{name: "/properties/a_set_maximum_minimum_items/type"},
{name: "/properties/a_string_enum_escaped_characters_kind_1/type"},
{name: "/properties/a_string_enum_escaped_characters_kind_2/type"},
{name: "/properties/a_string_enum_kind_1/type"},
{name: "/properties/a_string_enum_kind_2/type"},
{name: "/properties/a_string_length_over_defined/type"},
{name: "/properties/a_string_maximum_minimum_length/type"},
{name: "/properties/a_string_pattern_1/type"},
{name: "/properties/a_string_pattern_2/type"},
{name: "/properties/a_string_set_length/type"},
{name: "/properties/an_object_maximum_minimum_items/type"},
},
},
// null input on all fields, nullableAll is true
{
name: "simple null input nullableAll true",
filePath: "../../test/expected/simple/sample-input/test-input-null.json",
schemaPath: "../../test/expected/simple/schema-nullable-all.json",
keywordLocations: nil,
},
{
name: "simple-types null input nullableAll true",
filePath: "../../test/expected/simple-types/sample-input/test-input-null.json",
schemaPath: "../../test/expected/simple-types/schema-nullable-all.json",
keywordLocations: nil,
},
{
name: "complex-types null input nullableAll true",
filePath: "../../test/expected/complex-types/sample-input/test-input-null.json",
schemaPath: "../../test/expected/complex-types/schema-nullable-all.json",
keywordLocations: nil,
},
{
// of note: custom validation still applies to nullable fields, and sometimes 'null' doesn't satisfy the
// condition, meaning these fields effectively can't be null.
// This seems to primarily be the case for "enum" fields. Other fields tend to ignore this error, in JSON Schema.
name: "custom-validation null input nullableAll true",
filePath: "../../test/expected/custom-validation/sample-input/test-input-null.json",
schemaPath: "../../test/expected/custom-validation/schema-nullable-all.json",
keywordLocations: []errorLocation{
{name: "/properties/a_number_enum_kind_1/enum"},
{name: "/properties/a_number_enum_kind_2/enum"},
{name: "/properties/a_string_enum_kind_1/enum"},
{name: "/properties/a_string_enum_kind_2/enum"},
},
},
}
for i := range testCases {
tc := testCases[i]
Expand Down
3 changes: 2 additions & 1 deletion test/expected/complex-types/sample-input/test-input-all.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,6 @@
"b": 2,
"c": false,
"d": "Optional string"
}
},
"something_else": "string"
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@
"an_object_maximum_minimum_items": {
"name": "a",
"other_name": "this is an additional property, terraform will ignore it"
}
},
"something_else": "string"
}
3 changes: 2 additions & 1 deletion test/expected/simple-types/sample-input/test-input-all.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,6 @@
"a": "d",
"b": 2,
"c": false
}
},
"something_else": "string"
}
3 changes: 2 additions & 1 deletion test/expected/simple/sample-input/test-input-all.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"$schema": "../schema.json",
"name": "Aisling",
"age": 24
"age": 24,
"something_else": "string"
}

0 comments on commit 5560763

Please sign in to comment.