]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
common/options: validate see-also
authorKefu Chai <kchai@redhat.com>
Thu, 19 Aug 2021 09:24:32 +0000 (17:24 +0800)
committerKefu Chai <tchaikov@gmail.com>
Tue, 24 Aug 2021 14:22:37 +0000 (22:22 +0800)
y2c.py is like a compiler which translates .yaml to .cc and .h files,
it does not have access to all .yaml files. to validate the dangling
see-also issue, we need to do this with a "linker".

in this change, validate-options.py is introduced to check if any of
option name included by the see-also property is valid.

Fixes: https://tracker.ceph.com/issues/51483
Signed-off-by: Kefu Chai <kchai@redhat.com>
cmake/modules/AddCephTest.cmake
src/common/options/CMakeLists.txt
src/common/options/validate-options.py [new file with mode: 0755]

index af54e8a9c1a33d9deb13effc3dc79d56862c2005..0df7125b50833a7fd86d7bf05b9f364efafd1619 100644 (file)
@@ -2,7 +2,8 @@
 
 #adds makes target/script into a test, test to check target, sets necessary environment variables
 function(add_ceph_test test_name test_path)
-  add_test(NAME ${test_name} COMMAND ${test_path} ${ARGN})
+  add_test(NAME ${test_name} COMMAND ${test_path} ${ARGN}
+    COMMAND_EXPAND_LISTS)
   if(TARGET ${test_name})
     add_dependencies(tests ${test_name})
     set_property(TARGET ${test_name}
index 86de2e7972c803503229c403f046ac34f2744a13..b2b50716466ca044068ac57fe04b004f85434296 100644 (file)
@@ -1,5 +1,6 @@
 set(common_options_srcs build_options.cc)
 set(legacy_options_headers)
+set(options_yamls)
 
 # to mimic the behavior of file(CONFIGURE ...)
 file(GENERATE OUTPUT configure_file.cmake
@@ -26,6 +27,8 @@ function(add_options name)
   set(yaml_file ${CMAKE_CURRENT_BINARY_DIR}/${name}.yaml)
   file_configure("${yaml_in_file}"
     "${yaml_file}" @ONLY)
+  list(APPEND options_yamls ${yaml_file})
+  set(options_yamls ${options_yamls} PARENT_SCOPE)
   set(cc_file "${name}_options.cc")
   set(h_file "${PROJECT_BINARY_DIR}/include/${name}_legacy_options.h")
   add_custom_command(PRE_BUILD
@@ -102,3 +105,7 @@ add_library(common-options-objs OBJECT
   ${common_options_srcs})
 add_custom_target(legacy-option-headers
   DEPENDS ${legacy_options_headers})
+
+include(AddCephTest)
+add_ceph_test(validate-options
+  ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/validate-options.py ${options_yamls})
diff --git a/src/common/options/validate-options.py b/src/common/options/validate-options.py
new file mode 100755 (executable)
index 0000000..5bc5d4d
--- /dev/null
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+
+import argparse
+import fileinput
+import sys
+import yaml
+from typing import Any, Dict
+
+
+class ValidationError(Exception):
+    pass
+
+
+OptionType = Dict[str, Any]
+
+
+def validate_see_also(opt: OptionType, opts: Dict[str, OptionType]) -> None:
+    see_also = opt.get('see_also')
+    if see_also is None:
+        return
+    for ref in see_also:
+        if ref not in opts:
+            msg = f'see_also contains "{ref}". But it is not found.'
+            raise ValidationError(msg)
+
+
+def main() -> None:
+    parser = argparse.ArgumentParser(
+        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
+    parser.add_argument('yamls', nargs='*')
+    opts = parser.parse_args()
+    options = {}
+    for yaml_file in opts.yamls:
+        with open(yaml_file) as f:
+            yml = yaml.load(f, yaml.SafeLoader)
+            options.update({opt['name']: opt for opt in yml['options']})
+    for name, opt in options.items():
+        try:
+            validate_see_also(opt, options)
+        except ValidationError as e:
+            raise Exception(f'failed to validate "{name}": {e}')
+
+
+if __name__ == '__main__':
+    try:
+        main()
+    except Exception as e:
+        print(e, file=sys.stderr)
+        sys.exit(1)