xref: /aosp_15_r20/build/bazel/utils/schema_validation_test.bzl (revision 7594170e27e0732bc44b93d1440d87a54b6ffe7c)
1*7594170eSAndroid Build Coastguard Worker# Copyright (C) 2023 The Android Open Source Project
2*7594170eSAndroid Build Coastguard Worker#
3*7594170eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*7594170eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*7594170eSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*7594170eSAndroid Build Coastguard Worker#
7*7594170eSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
8*7594170eSAndroid Build Coastguard Worker#
9*7594170eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*7594170eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*7594170eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*7594170eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*7594170eSAndroid Build Coastguard Worker# limitations under the License.
14*7594170eSAndroid Build Coastguard Worker"""Tests for the validate() function."""
15*7594170eSAndroid Build Coastguard Worker
16*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//lib:unittest.bzl", "analysistest")
17*7594170eSAndroid Build Coastguard Workerload(":schema_validation.scl", "validate")
18*7594170eSAndroid Build Coastguard Worker
19*7594170eSAndroid Build Coastguard Workerdef _string_comparison_test_impl(ctx):
20*7594170eSAndroid Build Coastguard Worker    env = analysistest.begin(ctx)
21*7594170eSAndroid Build Coastguard Worker    if ctx.attr.actual != ctx.attr.expected:
22*7594170eSAndroid Build Coastguard Worker        analysistest.fail(env, "expected '%s' but got '%s'" % (ctx.attr.expected, ctx.attr.actual))
23*7594170eSAndroid Build Coastguard Worker    return analysistest.end(env)
24*7594170eSAndroid Build Coastguard Worker
25*7594170eSAndroid Build Coastguard Worker_string_comparison_raw_test = analysistest.make(
26*7594170eSAndroid Build Coastguard Worker    _string_comparison_test_impl,
27*7594170eSAndroid Build Coastguard Worker    attrs = {
28*7594170eSAndroid Build Coastguard Worker        "actual": attr.string(),
29*7594170eSAndroid Build Coastguard Worker        "expected": attr.string(),
30*7594170eSAndroid Build Coastguard Worker    },
31*7594170eSAndroid Build Coastguard Worker)
32*7594170eSAndroid Build Coastguard Worker
33*7594170eSAndroid Build Coastguard Workerdef _string_comparison_test(*, name, actual, expected):
34*7594170eSAndroid Build Coastguard Worker    _string_comparison_raw_test(
35*7594170eSAndroid Build Coastguard Worker        name = name,
36*7594170eSAndroid Build Coastguard Worker        actual = actual,
37*7594170eSAndroid Build Coastguard Worker        expected = expected,
38*7594170eSAndroid Build Coastguard Worker        # target_under_test is required but unused
39*7594170eSAndroid Build Coastguard Worker        target_under_test = "//build/bazel/utils:always_on_config_setting",
40*7594170eSAndroid Build Coastguard Worker    )
41*7594170eSAndroid Build Coastguard Worker
42*7594170eSAndroid Build Coastguard Workerdef _test_string_success():
43*7594170eSAndroid Build Coastguard Worker    test_name = "test_string_success"
44*7594170eSAndroid Build Coastguard Worker    data = "hello, world"
45*7594170eSAndroid Build Coastguard Worker    schema = {"type": "string"}
46*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
47*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
48*7594170eSAndroid Build Coastguard Worker        name = test_name,
49*7594170eSAndroid Build Coastguard Worker        expected = "",
50*7594170eSAndroid Build Coastguard Worker        actual = message,
51*7594170eSAndroid Build Coastguard Worker    )
52*7594170eSAndroid Build Coastguard Worker    return test_name
53*7594170eSAndroid Build Coastguard Worker
54*7594170eSAndroid Build Coastguard Workerdef _choices_success():
55*7594170eSAndroid Build Coastguard Worker    test_name = "choices_success"
56*7594170eSAndroid Build Coastguard Worker    data = "bar"
57*7594170eSAndroid Build Coastguard Worker    schema = {
58*7594170eSAndroid Build Coastguard Worker        "type": "string",
59*7594170eSAndroid Build Coastguard Worker        "choices": [
60*7594170eSAndroid Build Coastguard Worker            "foo",
61*7594170eSAndroid Build Coastguard Worker            "bar",
62*7594170eSAndroid Build Coastguard Worker            "baz",
63*7594170eSAndroid Build Coastguard Worker        ],
64*7594170eSAndroid Build Coastguard Worker    }
65*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
66*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
67*7594170eSAndroid Build Coastguard Worker        name = test_name,
68*7594170eSAndroid Build Coastguard Worker        expected = "",
69*7594170eSAndroid Build Coastguard Worker        actual = message,
70*7594170eSAndroid Build Coastguard Worker    )
71*7594170eSAndroid Build Coastguard Worker    return test_name
72*7594170eSAndroid Build Coastguard Worker
73*7594170eSAndroid Build Coastguard Workerdef _choices_failure():
74*7594170eSAndroid Build Coastguard Worker    test_name = "choices_failure"
75*7594170eSAndroid Build Coastguard Worker    data = "qux"
76*7594170eSAndroid Build Coastguard Worker    schema = {
77*7594170eSAndroid Build Coastguard Worker        "type": "string",
78*7594170eSAndroid Build Coastguard Worker        "choices": [
79*7594170eSAndroid Build Coastguard Worker            "foo",
80*7594170eSAndroid Build Coastguard Worker            "bar",
81*7594170eSAndroid Build Coastguard Worker            "baz",
82*7594170eSAndroid Build Coastguard Worker        ],
83*7594170eSAndroid Build Coastguard Worker    }
84*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
85*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
86*7594170eSAndroid Build Coastguard Worker        name = test_name,
87*7594170eSAndroid Build Coastguard Worker        expected = 'Expected one of ["foo", "bar", "baz"], got qux',
88*7594170eSAndroid Build Coastguard Worker        actual = message,
89*7594170eSAndroid Build Coastguard Worker    )
90*7594170eSAndroid Build Coastguard Worker    return test_name
91*7594170eSAndroid Build Coastguard Worker
92*7594170eSAndroid Build Coastguard Workerdef _value_success():
93*7594170eSAndroid Build Coastguard Worker    test_name = "value_success"
94*7594170eSAndroid Build Coastguard Worker    data = "bar"
95*7594170eSAndroid Build Coastguard Worker    schema = {
96*7594170eSAndroid Build Coastguard Worker        "type": "string",
97*7594170eSAndroid Build Coastguard Worker        "value": "bar",
98*7594170eSAndroid Build Coastguard Worker    }
99*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
100*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
101*7594170eSAndroid Build Coastguard Worker        name = test_name,
102*7594170eSAndroid Build Coastguard Worker        expected = "",
103*7594170eSAndroid Build Coastguard Worker        actual = message,
104*7594170eSAndroid Build Coastguard Worker    )
105*7594170eSAndroid Build Coastguard Worker    return test_name
106*7594170eSAndroid Build Coastguard Worker
107*7594170eSAndroid Build Coastguard Workerdef _value_failure():
108*7594170eSAndroid Build Coastguard Worker    test_name = "value_failure"
109*7594170eSAndroid Build Coastguard Worker    data = "qux"
110*7594170eSAndroid Build Coastguard Worker    schema = {
111*7594170eSAndroid Build Coastguard Worker        "type": "string",
112*7594170eSAndroid Build Coastguard Worker        "value": "bar",
113*7594170eSAndroid Build Coastguard Worker    }
114*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
115*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
116*7594170eSAndroid Build Coastguard Worker        name = test_name,
117*7594170eSAndroid Build Coastguard Worker        expected = "Expected bar, got qux",
118*7594170eSAndroid Build Coastguard Worker        actual = message,
119*7594170eSAndroid Build Coastguard Worker    )
120*7594170eSAndroid Build Coastguard Worker    return test_name
121*7594170eSAndroid Build Coastguard Worker
122*7594170eSAndroid Build Coastguard Workerdef _length_success():
123*7594170eSAndroid Build Coastguard Worker    test_name = "length_success"
124*7594170eSAndroid Build Coastguard Worker    data = {
125*7594170eSAndroid Build Coastguard Worker        "a": "foo",
126*7594170eSAndroid Build Coastguard Worker        "b": "foo",
127*7594170eSAndroid Build Coastguard Worker        "c": "foo",
128*7594170eSAndroid Build Coastguard Worker        "d": "foo",
129*7594170eSAndroid Build Coastguard Worker        "e": "foo",
130*7594170eSAndroid Build Coastguard Worker        "f": "foo",
131*7594170eSAndroid Build Coastguard Worker    }
132*7594170eSAndroid Build Coastguard Worker    schema = {
133*7594170eSAndroid Build Coastguard Worker        "type": "dict",
134*7594170eSAndroid Build Coastguard Worker        "required_keys": {
135*7594170eSAndroid Build Coastguard Worker            "a": {
136*7594170eSAndroid Build Coastguard Worker                "type": "string",
137*7594170eSAndroid Build Coastguard Worker                "length": 3,
138*7594170eSAndroid Build Coastguard Worker            },
139*7594170eSAndroid Build Coastguard Worker            "b": {
140*7594170eSAndroid Build Coastguard Worker                "type": "string",
141*7594170eSAndroid Build Coastguard Worker                "length": "<4",
142*7594170eSAndroid Build Coastguard Worker            },
143*7594170eSAndroid Build Coastguard Worker            "c": {
144*7594170eSAndroid Build Coastguard Worker                "type": "string",
145*7594170eSAndroid Build Coastguard Worker                "length": "<=4",
146*7594170eSAndroid Build Coastguard Worker            },
147*7594170eSAndroid Build Coastguard Worker            "d": {
148*7594170eSAndroid Build Coastguard Worker                "type": "string",
149*7594170eSAndroid Build Coastguard Worker                "length": ">2",
150*7594170eSAndroid Build Coastguard Worker            },
151*7594170eSAndroid Build Coastguard Worker            "e": {
152*7594170eSAndroid Build Coastguard Worker                "type": "string",
153*7594170eSAndroid Build Coastguard Worker                "length": ">=2",
154*7594170eSAndroid Build Coastguard Worker            },
155*7594170eSAndroid Build Coastguard Worker            "f": {
156*7594170eSAndroid Build Coastguard Worker                "type": "string",
157*7594170eSAndroid Build Coastguard Worker                "length": "=3",
158*7594170eSAndroid Build Coastguard Worker            },
159*7594170eSAndroid Build Coastguard Worker        },
160*7594170eSAndroid Build Coastguard Worker    }
161*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
162*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
163*7594170eSAndroid Build Coastguard Worker        name = test_name,
164*7594170eSAndroid Build Coastguard Worker        expected = "",
165*7594170eSAndroid Build Coastguard Worker        actual = message,
166*7594170eSAndroid Build Coastguard Worker    )
167*7594170eSAndroid Build Coastguard Worker    return test_name
168*7594170eSAndroid Build Coastguard Worker
169*7594170eSAndroid Build Coastguard Workerdef _length_failure_1():
170*7594170eSAndroid Build Coastguard Worker    test_name = "length_failure_1"
171*7594170eSAndroid Build Coastguard Worker    data = "qux"
172*7594170eSAndroid Build Coastguard Worker    schema = {
173*7594170eSAndroid Build Coastguard Worker        "type": "string",
174*7594170eSAndroid Build Coastguard Worker        "length": 4,
175*7594170eSAndroid Build Coastguard Worker    }
176*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
177*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
178*7594170eSAndroid Build Coastguard Worker        name = test_name,
179*7594170eSAndroid Build Coastguard Worker        expected = "Expected length 4, got 3",
180*7594170eSAndroid Build Coastguard Worker        actual = message,
181*7594170eSAndroid Build Coastguard Worker    )
182*7594170eSAndroid Build Coastguard Worker    return test_name
183*7594170eSAndroid Build Coastguard Worker
184*7594170eSAndroid Build Coastguard Workerdef _length_failure_2():
185*7594170eSAndroid Build Coastguard Worker    test_name = "length_failure_2"
186*7594170eSAndroid Build Coastguard Worker    data = "qux"
187*7594170eSAndroid Build Coastguard Worker    schema = {
188*7594170eSAndroid Build Coastguard Worker        "type": "string",
189*7594170eSAndroid Build Coastguard Worker        "length": ">3",
190*7594170eSAndroid Build Coastguard Worker    }
191*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
192*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
193*7594170eSAndroid Build Coastguard Worker        name = test_name,
194*7594170eSAndroid Build Coastguard Worker        expected = "Expected length >3, got 3",
195*7594170eSAndroid Build Coastguard Worker        actual = message,
196*7594170eSAndroid Build Coastguard Worker    )
197*7594170eSAndroid Build Coastguard Worker    return test_name
198*7594170eSAndroid Build Coastguard Worker
199*7594170eSAndroid Build Coastguard Workerdef _test_type_failure():
200*7594170eSAndroid Build Coastguard Worker    test_name = "test_type_failure"
201*7594170eSAndroid Build Coastguard Worker    data = 5
202*7594170eSAndroid Build Coastguard Worker    schema = {"type": "string"}
203*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
204*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
205*7594170eSAndroid Build Coastguard Worker        name = test_name,
206*7594170eSAndroid Build Coastguard Worker        expected = "Expected string, got int",
207*7594170eSAndroid Build Coastguard Worker        actual = message,
208*7594170eSAndroid Build Coastguard Worker    )
209*7594170eSAndroid Build Coastguard Worker    return test_name
210*7594170eSAndroid Build Coastguard Worker
211*7594170eSAndroid Build Coastguard Workerdef _test_or_success():
212*7594170eSAndroid Build Coastguard Worker    test_name = "test_or_success"
213*7594170eSAndroid Build Coastguard Worker    data = "hello, world"
214*7594170eSAndroid Build Coastguard Worker    schema = {"or": [
215*7594170eSAndroid Build Coastguard Worker        {"type": "int"},
216*7594170eSAndroid Build Coastguard Worker        {"type": "string"},
217*7594170eSAndroid Build Coastguard Worker    ]}
218*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
219*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
220*7594170eSAndroid Build Coastguard Worker        name = test_name,
221*7594170eSAndroid Build Coastguard Worker        expected = "",
222*7594170eSAndroid Build Coastguard Worker        actual = message,
223*7594170eSAndroid Build Coastguard Worker    )
224*7594170eSAndroid Build Coastguard Worker    return test_name
225*7594170eSAndroid Build Coastguard Worker
226*7594170eSAndroid Build Coastguard Workerdef _test_or_failure():
227*7594170eSAndroid Build Coastguard Worker    test_name = "test_or_failure"
228*7594170eSAndroid Build Coastguard Worker    data = 3.5
229*7594170eSAndroid Build Coastguard Worker    schema = {"or": [
230*7594170eSAndroid Build Coastguard Worker        {"type": "int"},
231*7594170eSAndroid Build Coastguard Worker        {"type": "string"},
232*7594170eSAndroid Build Coastguard Worker    ]}
233*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
234*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
235*7594170eSAndroid Build Coastguard Worker        name = test_name,
236*7594170eSAndroid Build Coastguard Worker        expected = "did not match any schemas in 'or' list, errors:\n  Expected int, got float\n  Expected string, got float",
237*7594170eSAndroid Build Coastguard Worker        actual = message,
238*7594170eSAndroid Build Coastguard Worker    )
239*7594170eSAndroid Build Coastguard Worker    return test_name
240*7594170eSAndroid Build Coastguard Worker
241*7594170eSAndroid Build Coastguard Workerdef _list_of_strings_success():
242*7594170eSAndroid Build Coastguard Worker    test_name = "list_of_strings_success"
243*7594170eSAndroid Build Coastguard Worker    data = ["a", "b"]
244*7594170eSAndroid Build Coastguard Worker    schema = {
245*7594170eSAndroid Build Coastguard Worker        "type": "list",
246*7594170eSAndroid Build Coastguard Worker        "of": {"type": "string"},
247*7594170eSAndroid Build Coastguard Worker    }
248*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
249*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
250*7594170eSAndroid Build Coastguard Worker        name = test_name,
251*7594170eSAndroid Build Coastguard Worker        expected = "",
252*7594170eSAndroid Build Coastguard Worker        actual = message,
253*7594170eSAndroid Build Coastguard Worker    )
254*7594170eSAndroid Build Coastguard Worker    return test_name
255*7594170eSAndroid Build Coastguard Worker
256*7594170eSAndroid Build Coastguard Workerdef _list_of_strings_failure():
257*7594170eSAndroid Build Coastguard Worker    test_name = "list_of_strings_failure"
258*7594170eSAndroid Build Coastguard Worker    data = ["a", 5, "b"]
259*7594170eSAndroid Build Coastguard Worker    schema = {
260*7594170eSAndroid Build Coastguard Worker        "type": "list",
261*7594170eSAndroid Build Coastguard Worker        "of": {"type": "string"},
262*7594170eSAndroid Build Coastguard Worker    }
263*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
264*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
265*7594170eSAndroid Build Coastguard Worker        name = test_name,
266*7594170eSAndroid Build Coastguard Worker        expected = "Expected string, got int",
267*7594170eSAndroid Build Coastguard Worker        actual = message,
268*7594170eSAndroid Build Coastguard Worker    )
269*7594170eSAndroid Build Coastguard Worker    return test_name
270*7594170eSAndroid Build Coastguard Worker
271*7594170eSAndroid Build Coastguard Workerdef _tuple_of_strings_success():
272*7594170eSAndroid Build Coastguard Worker    test_name = "tuple_of_strings_success"
273*7594170eSAndroid Build Coastguard Worker    data = ("a", "b")
274*7594170eSAndroid Build Coastguard Worker    schema = {
275*7594170eSAndroid Build Coastguard Worker        "type": "tuple",
276*7594170eSAndroid Build Coastguard Worker        "of": {"type": "string"},
277*7594170eSAndroid Build Coastguard Worker    }
278*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
279*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
280*7594170eSAndroid Build Coastguard Worker        name = test_name,
281*7594170eSAndroid Build Coastguard Worker        expected = "",
282*7594170eSAndroid Build Coastguard Worker        actual = message,
283*7594170eSAndroid Build Coastguard Worker    )
284*7594170eSAndroid Build Coastguard Worker    return test_name
285*7594170eSAndroid Build Coastguard Worker
286*7594170eSAndroid Build Coastguard Workerdef _tuple_of_strings_failure():
287*7594170eSAndroid Build Coastguard Worker    test_name = "tuple_of_strings_failure"
288*7594170eSAndroid Build Coastguard Worker    data = ("a", 5, "b")
289*7594170eSAndroid Build Coastguard Worker    schema = {
290*7594170eSAndroid Build Coastguard Worker        "type": "tuple",
291*7594170eSAndroid Build Coastguard Worker        "of": {"type": "string"},
292*7594170eSAndroid Build Coastguard Worker    }
293*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
294*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
295*7594170eSAndroid Build Coastguard Worker        name = test_name,
296*7594170eSAndroid Build Coastguard Worker        expected = "Expected string, got int",
297*7594170eSAndroid Build Coastguard Worker        actual = message,
298*7594170eSAndroid Build Coastguard Worker    )
299*7594170eSAndroid Build Coastguard Worker    return test_name
300*7594170eSAndroid Build Coastguard Worker
301*7594170eSAndroid Build Coastguard Workerdef _unique_list_of_strings_success():
302*7594170eSAndroid Build Coastguard Worker    test_name = "unique_list_of_strings_success"
303*7594170eSAndroid Build Coastguard Worker    data = ["a", "b"]
304*7594170eSAndroid Build Coastguard Worker    schema = {
305*7594170eSAndroid Build Coastguard Worker        "type": "list",
306*7594170eSAndroid Build Coastguard Worker        "of": {"type": "string"},
307*7594170eSAndroid Build Coastguard Worker        "unique": True,
308*7594170eSAndroid Build Coastguard Worker    }
309*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
310*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
311*7594170eSAndroid Build Coastguard Worker        name = test_name,
312*7594170eSAndroid Build Coastguard Worker        expected = "",
313*7594170eSAndroid Build Coastguard Worker        actual = message,
314*7594170eSAndroid Build Coastguard Worker    )
315*7594170eSAndroid Build Coastguard Worker    return test_name
316*7594170eSAndroid Build Coastguard Worker
317*7594170eSAndroid Build Coastguard Workerdef _unique_list_of_strings_failure():
318*7594170eSAndroid Build Coastguard Worker    test_name = "unique_list_of_strings_failure"
319*7594170eSAndroid Build Coastguard Worker    data = ["a", "b", "a"]
320*7594170eSAndroid Build Coastguard Worker    schema = {
321*7594170eSAndroid Build Coastguard Worker        "type": "list",
322*7594170eSAndroid Build Coastguard Worker        "of": {"type": "string"},
323*7594170eSAndroid Build Coastguard Worker        "unique": True,
324*7594170eSAndroid Build Coastguard Worker    }
325*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
326*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
327*7594170eSAndroid Build Coastguard Worker        name = test_name,
328*7594170eSAndroid Build Coastguard Worker        expected = "Expected all elements to be unique, but saw 'a' twice",
329*7594170eSAndroid Build Coastguard Worker        actual = message,
330*7594170eSAndroid Build Coastguard Worker    )
331*7594170eSAndroid Build Coastguard Worker    return test_name
332*7594170eSAndroid Build Coastguard Worker
333*7594170eSAndroid Build Coastguard Workerdef _dict_success():
334*7594170eSAndroid Build Coastguard Worker    test_name = "dict_success"
335*7594170eSAndroid Build Coastguard Worker    data = {
336*7594170eSAndroid Build Coastguard Worker        "foo": 5,
337*7594170eSAndroid Build Coastguard Worker        "bar": "baz",
338*7594170eSAndroid Build Coastguard Worker        "qux": 3.5,
339*7594170eSAndroid Build Coastguard Worker    }
340*7594170eSAndroid Build Coastguard Worker    schema = {
341*7594170eSAndroid Build Coastguard Worker        "type": "dict",
342*7594170eSAndroid Build Coastguard Worker        "required_keys": {
343*7594170eSAndroid Build Coastguard Worker            "foo": {"type": "int"},
344*7594170eSAndroid Build Coastguard Worker            "bar": {"type": "string"},
345*7594170eSAndroid Build Coastguard Worker        },
346*7594170eSAndroid Build Coastguard Worker        "optional_keys": {
347*7594170eSAndroid Build Coastguard Worker            "qux": {"type": "float"},
348*7594170eSAndroid Build Coastguard Worker        },
349*7594170eSAndroid Build Coastguard Worker    }
350*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
351*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
352*7594170eSAndroid Build Coastguard Worker        name = test_name,
353*7594170eSAndroid Build Coastguard Worker        expected = "",
354*7594170eSAndroid Build Coastguard Worker        actual = message,
355*7594170eSAndroid Build Coastguard Worker    )
356*7594170eSAndroid Build Coastguard Worker    return test_name
357*7594170eSAndroid Build Coastguard Worker
358*7594170eSAndroid Build Coastguard Workerdef _dict_missing_required_key():
359*7594170eSAndroid Build Coastguard Worker    test_name = "dict_missing_required_key"
360*7594170eSAndroid Build Coastguard Worker    data = {
361*7594170eSAndroid Build Coastguard Worker        "foo": 5,
362*7594170eSAndroid Build Coastguard Worker    }
363*7594170eSAndroid Build Coastguard Worker    schema = {
364*7594170eSAndroid Build Coastguard Worker        "type": "dict",
365*7594170eSAndroid Build Coastguard Worker        "required_keys": {
366*7594170eSAndroid Build Coastguard Worker            "foo": {"type": "int"},
367*7594170eSAndroid Build Coastguard Worker            "bar": {"type": "string"},
368*7594170eSAndroid Build Coastguard Worker        },
369*7594170eSAndroid Build Coastguard Worker    }
370*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
371*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
372*7594170eSAndroid Build Coastguard Worker        name = test_name,
373*7594170eSAndroid Build Coastguard Worker        expected = "required key 'bar' not found",
374*7594170eSAndroid Build Coastguard Worker        actual = message,
375*7594170eSAndroid Build Coastguard Worker    )
376*7594170eSAndroid Build Coastguard Worker    return test_name
377*7594170eSAndroid Build Coastguard Worker
378*7594170eSAndroid Build Coastguard Workerdef _dict_extra_keys():
379*7594170eSAndroid Build Coastguard Worker    test_name = "dict_extra_keys"
380*7594170eSAndroid Build Coastguard Worker    data = {
381*7594170eSAndroid Build Coastguard Worker        "foo": 5,
382*7594170eSAndroid Build Coastguard Worker        "bar": "hello",
383*7594170eSAndroid Build Coastguard Worker        "baz": 3.5,
384*7594170eSAndroid Build Coastguard Worker    }
385*7594170eSAndroid Build Coastguard Worker    schema = {
386*7594170eSAndroid Build Coastguard Worker        "type": "dict",
387*7594170eSAndroid Build Coastguard Worker        "required_keys": {
388*7594170eSAndroid Build Coastguard Worker            "foo": {"type": "int"},
389*7594170eSAndroid Build Coastguard Worker        },
390*7594170eSAndroid Build Coastguard Worker        "optional_keys": {
391*7594170eSAndroid Build Coastguard Worker            "bar": {"type": "string"},
392*7594170eSAndroid Build Coastguard Worker        },
393*7594170eSAndroid Build Coastguard Worker    }
394*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
395*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
396*7594170eSAndroid Build Coastguard Worker        name = test_name,
397*7594170eSAndroid Build Coastguard Worker        expected = 'keys ["baz"] not allowed, valid keys: ["foo", "bar"]',
398*7594170eSAndroid Build Coastguard Worker        actual = message,
399*7594170eSAndroid Build Coastguard Worker    )
400*7594170eSAndroid Build Coastguard Worker    return test_name
401*7594170eSAndroid Build Coastguard Worker
402*7594170eSAndroid Build Coastguard Workerdef _dict_generic_keys_success():
403*7594170eSAndroid Build Coastguard Worker    test_name = "dict_generic_keys_success"
404*7594170eSAndroid Build Coastguard Worker    data = {
405*7594170eSAndroid Build Coastguard Worker        "foo": 5,
406*7594170eSAndroid Build Coastguard Worker        "bar": "hello",
407*7594170eSAndroid Build Coastguard Worker    }
408*7594170eSAndroid Build Coastguard Worker    schema = {
409*7594170eSAndroid Build Coastguard Worker        "type": "dict",
410*7594170eSAndroid Build Coastguard Worker        "keys": {"type": "string"},
411*7594170eSAndroid Build Coastguard Worker        "values": {
412*7594170eSAndroid Build Coastguard Worker            "or": [
413*7594170eSAndroid Build Coastguard Worker                {"type": "string"},
414*7594170eSAndroid Build Coastguard Worker                {"type": "int"},
415*7594170eSAndroid Build Coastguard Worker            ],
416*7594170eSAndroid Build Coastguard Worker        },
417*7594170eSAndroid Build Coastguard Worker    }
418*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
419*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
420*7594170eSAndroid Build Coastguard Worker        name = test_name,
421*7594170eSAndroid Build Coastguard Worker        expected = "",
422*7594170eSAndroid Build Coastguard Worker        actual = message,
423*7594170eSAndroid Build Coastguard Worker    )
424*7594170eSAndroid Build Coastguard Worker    return test_name
425*7594170eSAndroid Build Coastguard Worker
426*7594170eSAndroid Build Coastguard Workerdef _dict_generic_keys_failure():
427*7594170eSAndroid Build Coastguard Worker    test_name = "dict_generic_keys_failure"
428*7594170eSAndroid Build Coastguard Worker    data = {
429*7594170eSAndroid Build Coastguard Worker        "foo": 5,
430*7594170eSAndroid Build Coastguard Worker        "bar": "hello",
431*7594170eSAndroid Build Coastguard Worker        "baz": 3.5,
432*7594170eSAndroid Build Coastguard Worker    }
433*7594170eSAndroid Build Coastguard Worker    schema = {
434*7594170eSAndroid Build Coastguard Worker        "type": "dict",
435*7594170eSAndroid Build Coastguard Worker        "keys": {"type": "string"},
436*7594170eSAndroid Build Coastguard Worker        "values": {
437*7594170eSAndroid Build Coastguard Worker            "or": [
438*7594170eSAndroid Build Coastguard Worker                {"type": "string"},
439*7594170eSAndroid Build Coastguard Worker                {"type": "int"},
440*7594170eSAndroid Build Coastguard Worker            ],
441*7594170eSAndroid Build Coastguard Worker        },
442*7594170eSAndroid Build Coastguard Worker    }
443*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
444*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
445*7594170eSAndroid Build Coastguard Worker        name = test_name,
446*7594170eSAndroid Build Coastguard Worker        expected = "did not match any schemas in 'or' list, errors:\n  Expected string, got float\n  Expected int, got float",
447*7594170eSAndroid Build Coastguard Worker        actual = message,
448*7594170eSAndroid Build Coastguard Worker    )
449*7594170eSAndroid Build Coastguard Worker    return test_name
450*7594170eSAndroid Build Coastguard Worker
451*7594170eSAndroid Build Coastguard Workerdef _struct_success():
452*7594170eSAndroid Build Coastguard Worker    test_name = "struct_success"
453*7594170eSAndroid Build Coastguard Worker    data = struct(
454*7594170eSAndroid Build Coastguard Worker        foo = 5,
455*7594170eSAndroid Build Coastguard Worker        bar = "baz",
456*7594170eSAndroid Build Coastguard Worker        qux = 3.5,
457*7594170eSAndroid Build Coastguard Worker    )
458*7594170eSAndroid Build Coastguard Worker    schema = {
459*7594170eSAndroid Build Coastguard Worker        "type": "struct",
460*7594170eSAndroid Build Coastguard Worker        "required_fields": {
461*7594170eSAndroid Build Coastguard Worker            "foo": {"type": "int"},
462*7594170eSAndroid Build Coastguard Worker            "bar": {"type": "string"},
463*7594170eSAndroid Build Coastguard Worker        },
464*7594170eSAndroid Build Coastguard Worker        "optional_fields": {
465*7594170eSAndroid Build Coastguard Worker            "qux": {"type": "float"},
466*7594170eSAndroid Build Coastguard Worker        },
467*7594170eSAndroid Build Coastguard Worker    }
468*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
469*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
470*7594170eSAndroid Build Coastguard Worker        name = test_name,
471*7594170eSAndroid Build Coastguard Worker        expected = "",
472*7594170eSAndroid Build Coastguard Worker        actual = message,
473*7594170eSAndroid Build Coastguard Worker    )
474*7594170eSAndroid Build Coastguard Worker    return test_name
475*7594170eSAndroid Build Coastguard Worker
476*7594170eSAndroid Build Coastguard Workerdef _struct_missing_required_field():
477*7594170eSAndroid Build Coastguard Worker    test_name = "struct_missing_required_field"
478*7594170eSAndroid Build Coastguard Worker    data = struct(
479*7594170eSAndroid Build Coastguard Worker        foo = 5,
480*7594170eSAndroid Build Coastguard Worker    )
481*7594170eSAndroid Build Coastguard Worker    schema = {
482*7594170eSAndroid Build Coastguard Worker        "type": "struct",
483*7594170eSAndroid Build Coastguard Worker        "required_fields": {
484*7594170eSAndroid Build Coastguard Worker            "foo": {"type": "int"},
485*7594170eSAndroid Build Coastguard Worker            "bar": {"type": "string"},
486*7594170eSAndroid Build Coastguard Worker        },
487*7594170eSAndroid Build Coastguard Worker    }
488*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
489*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
490*7594170eSAndroid Build Coastguard Worker        name = test_name,
491*7594170eSAndroid Build Coastguard Worker        expected = "required field 'bar' not found",
492*7594170eSAndroid Build Coastguard Worker        actual = message,
493*7594170eSAndroid Build Coastguard Worker    )
494*7594170eSAndroid Build Coastguard Worker    return test_name
495*7594170eSAndroid Build Coastguard Worker
496*7594170eSAndroid Build Coastguard Workerdef _struct_extra_fields():
497*7594170eSAndroid Build Coastguard Worker    test_name = "struct_extra_fields"
498*7594170eSAndroid Build Coastguard Worker    data = struct(
499*7594170eSAndroid Build Coastguard Worker        foo = 5,
500*7594170eSAndroid Build Coastguard Worker        bar = "baz",
501*7594170eSAndroid Build Coastguard Worker        baz = 3.5,
502*7594170eSAndroid Build Coastguard Worker    )
503*7594170eSAndroid Build Coastguard Worker    schema = {
504*7594170eSAndroid Build Coastguard Worker        "type": "struct",
505*7594170eSAndroid Build Coastguard Worker        "required_fields": {
506*7594170eSAndroid Build Coastguard Worker            "foo": {"type": "int"},
507*7594170eSAndroid Build Coastguard Worker        },
508*7594170eSAndroid Build Coastguard Worker        "optional_fields": {
509*7594170eSAndroid Build Coastguard Worker            "bar": {"type": "string"},
510*7594170eSAndroid Build Coastguard Worker        },
511*7594170eSAndroid Build Coastguard Worker    }
512*7594170eSAndroid Build Coastguard Worker    message = validate(data, schema, fail_on_error = False)
513*7594170eSAndroid Build Coastguard Worker    _string_comparison_test(
514*7594170eSAndroid Build Coastguard Worker        name = test_name,
515*7594170eSAndroid Build Coastguard Worker        expected = 'fields ["baz"] not allowed, valid keys: ["foo", "bar"]',
516*7594170eSAndroid Build Coastguard Worker        actual = message,
517*7594170eSAndroid Build Coastguard Worker    )
518*7594170eSAndroid Build Coastguard Worker    return test_name
519*7594170eSAndroid Build Coastguard Worker
520*7594170eSAndroid Build Coastguard Workerdef schema_validation_test_suite(name):
521*7594170eSAndroid Build Coastguard Worker    native.test_suite(
522*7594170eSAndroid Build Coastguard Worker        name = name,
523*7594170eSAndroid Build Coastguard Worker        tests = [
524*7594170eSAndroid Build Coastguard Worker            _test_string_success(),
525*7594170eSAndroid Build Coastguard Worker            _choices_success(),
526*7594170eSAndroid Build Coastguard Worker            _choices_failure(),
527*7594170eSAndroid Build Coastguard Worker            _value_success(),
528*7594170eSAndroid Build Coastguard Worker            _value_failure(),
529*7594170eSAndroid Build Coastguard Worker            _length_success(),
530*7594170eSAndroid Build Coastguard Worker            _length_failure_1(),
531*7594170eSAndroid Build Coastguard Worker            _length_failure_2(),
532*7594170eSAndroid Build Coastguard Worker            _test_type_failure(),
533*7594170eSAndroid Build Coastguard Worker            _test_or_success(),
534*7594170eSAndroid Build Coastguard Worker            _test_or_failure(),
535*7594170eSAndroid Build Coastguard Worker            _list_of_strings_success(),
536*7594170eSAndroid Build Coastguard Worker            _list_of_strings_failure(),
537*7594170eSAndroid Build Coastguard Worker            _tuple_of_strings_success(),
538*7594170eSAndroid Build Coastguard Worker            _tuple_of_strings_failure(),
539*7594170eSAndroid Build Coastguard Worker            _unique_list_of_strings_success(),
540*7594170eSAndroid Build Coastguard Worker            _unique_list_of_strings_failure(),
541*7594170eSAndroid Build Coastguard Worker            _dict_success(),
542*7594170eSAndroid Build Coastguard Worker            _dict_missing_required_key(),
543*7594170eSAndroid Build Coastguard Worker            _dict_extra_keys(),
544*7594170eSAndroid Build Coastguard Worker            _dict_generic_keys_success(),
545*7594170eSAndroid Build Coastguard Worker            _dict_generic_keys_failure(),
546*7594170eSAndroid Build Coastguard Worker            _struct_success(),
547*7594170eSAndroid Build Coastguard Worker            _struct_missing_required_field(),
548*7594170eSAndroid Build Coastguard Worker            _struct_extra_fields(),
549*7594170eSAndroid Build Coastguard Worker        ],
550*7594170eSAndroid Build Coastguard Worker    )
551