Add "unique" option to validate lists of unique elements
Test: b test //build/bazel/utils:schema_validation_test_suite --test_output=errors
Change-Id: I72fdc5a258ccf245a907e61352b1671b3408564e
diff --git a/utils/schema_validation.bzl b/utils/schema_validation.bzl
index 9599dc5..db093fb 100644
--- a/utils/schema_validation.bzl
+++ b/utils/schema_validation.bzl
@@ -57,6 +57,7 @@
],
},
"of": {}, # to be filled in later
+ "unique": {"type": "bool"},
"length": {"or": [
{"type": "string"},
{"type": "int"},
@@ -177,6 +178,24 @@
ret = "Expected %s, got %s" % (schema["value"], obj)
stack.pop()
continue
+ if schema.get("unique", False):
+ if ty != "list" and ty != "tuple":
+ fail("'unique' is only valid for lists or tuples, got: " + ty)
+ l = sorted(obj)
+ done = False
+ for i in range(len(l) - 1):
+ if type(l[i]) not in ["string", "int", "float", "bool", "NoneType", "bytes"]:
+ ret = "'unique' only works on lists/tuples of scalar types, got: " + type(l[i])
+ stack.pop()
+ done = True
+ break
+ if l[i] == l[i + 1]:
+ ret = "Expected all elements to be unique, but saw '%s' twice" % str(l[i])
+ stack.pop()
+ done = True
+ break
+ if done:
+ continue
if "of" in schema:
if ty != "list" and ty != "tuple":
fail("'of' is only valid for lists or tuples, got: " + ty)
diff --git a/utils/schema_validation_test.bzl b/utils/schema_validation_test.bzl
index 9a5c772..131e643 100644
--- a/utils/schema_validation_test.bzl
+++ b/utils/schema_validation_test.bzl
@@ -298,6 +298,38 @@
)
return test_name
+def _unique_list_of_strings_success():
+ test_name = "unique_list_of_strings_success"
+ data = ["a", "b"]
+ schema = {
+ "type": "list",
+ "of": {"type": "string"},
+ "unique": True,
+ }
+ message = validate(data, schema, fail_on_error = False)
+ _string_comparison_test(
+ name = test_name,
+ expected = "",
+ actual = message,
+ )
+ return test_name
+
+def _unique_list_of_strings_failure():
+ test_name = "unique_list_of_strings_failure"
+ data = ["a", "b", "a"]
+ schema = {
+ "type": "list",
+ "of": {"type": "string"},
+ "unique": True,
+ }
+ message = validate(data, schema, fail_on_error = False)
+ _string_comparison_test(
+ name = test_name,
+ expected = "Expected all elements to be unique, but saw 'a' twice",
+ actual = message,
+ )
+ return test_name
+
def _dict_success():
test_name = "dict_success"
data = {
@@ -504,6 +536,8 @@
_list_of_strings_failure(),
_tuple_of_strings_success(),
_tuple_of_strings_failure(),
+ _unique_list_of_strings_success(),
+ _unique_list_of_strings_failure(),
_dict_success(),
_dict_missing_required_key(),
_dict_extra_keys(),