Skip to content

Commit

Permalink
Add tests for the other kinds of schema
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 committed Aug 30, 2024
1 parent 3995cff commit 0a40089
Show file tree
Hide file tree
Showing 6 changed files with 142 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
133 changes: 133 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,9 +309,104 @@ 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]
if tc.name != "custom-validation null input nullableAll true" {
continue
}
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
path, err := filepath.Abs(tc.schemaPath)
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 0a40089

Please sign in to comment.