check-json.cmake 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. cmake_policy(PUSH)
  2. cmake_policy(SET CMP0057 NEW)
  3. function (json_placeholders in out)
  4. string(REPLACE "<CONFIG>" "${CXXModules_config}" in "${in}")
  5. if (RunCMake_GENERATOR_IS_MULTI_CONFIG)
  6. string(REPLACE "<CONFIG_DIR>" "/${CXXModules_config}" in "${in}")
  7. else ()
  8. string(REPLACE "<CONFIG_DIR>" "" in "${in}")
  9. endif ()
  10. if (CMAKE_BUILD_TYPE)
  11. string(REPLACE "<CONFIG_FORCE>" "${CXXModules_config}" in "${in}")
  12. else ()
  13. string(REPLACE "<CONFIG_FORCE>" "noconfig" in "${in}")
  14. endif ()
  15. string(REPLACE "<SOURCE_DIR>" "${RunCMake_SOURCE_DIR}" in "${in}")
  16. string(REPLACE "<BINARY_DIR>" "${RunCMake_TEST_BINARY_DIR}" in "${in}")
  17. string(REPLACE "<OBJEXT>" "${CMAKE_CXX_OUTPUT_EXTENSION}" in "${in}")
  18. set("${out}" "${in}" PARENT_SCOPE)
  19. endfunction ()
  20. function (check_json_value path actual_type expect_type actual_value expect_value)
  21. if (NOT actual_type STREQUAL expect_type)
  22. list(APPEND RunCMake_TEST_FAILED
  23. "Type mismatch at ${path}: ${actual_type} vs. ${expect_type}")
  24. set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
  25. return ()
  26. endif ()
  27. if (actual_type STREQUAL NULL)
  28. # Nothing to check
  29. elseif (actual_type STREQUAL BOOLEAN)
  30. if (NOT actual_value STREQUAL expect_value)
  31. list(APPEND RunCMake_TEST_FAILED
  32. "Boolean mismatch at ${path}: ${actual_value} vs. ${expect_value}")
  33. endif ()
  34. elseif (actual_type STREQUAL NUMBER)
  35. if (NOT actual_value EQUAL expect_value)
  36. list(APPEND RunCMake_TEST_FAILED
  37. "Number mismatch at ${path}: ${actual_value} vs. ${expect_value}")
  38. endif ()
  39. elseif (actual_type STREQUAL STRING)
  40. # Allow some values to be ignored.
  41. if (expect_value STREQUAL "<IGNORE>")
  42. return ()
  43. endif ()
  44. json_placeholders("${expect_value}" expect_value_expanded)
  45. if (NOT actual_value STREQUAL expect_value_expanded)
  46. list(APPEND RunCMake_TEST_FAILED
  47. "String mismatch at ${path}: ${actual_value} vs. ${expect_value_expanded}")
  48. endif ()
  49. elseif (actual_type STREQUAL ARRAY)
  50. check_json_array("${path}" "${actual_value}" "${expect_value}")
  51. elseif (actual_type STREQUAL OBJECT)
  52. check_json_object("${path}" "${actual_value}" "${expect_value}")
  53. endif ()
  54. set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
  55. endfunction ()
  56. # Check that two arrays are the same.
  57. function (check_json_array path actual expect)
  58. string(JSON actual_len LENGTH "${actual}")
  59. string(JSON expect_len LENGTH "${expect}")
  60. set(iter_len "${actual_len}")
  61. if (actual_len LESS expect_len)
  62. list(APPEND RunCMake_TEST_FAILED
  63. "Missing array items at ${path}")
  64. elseif (expect_len LESS actual_len)
  65. list(APPEND RunCMake_TEST_FAILED
  66. "Extra array items at ${path}")
  67. set(iter_len "${expect_len}")
  68. endif ()
  69. foreach (idx RANGE "${iter_len}")
  70. if (idx EQUAL iter_len)
  71. break ()
  72. endif ()
  73. set(new_path "${path}[${idx}]")
  74. string(JSON actual_type TYPE "${actual}" "${idx}")
  75. string(JSON expect_type TYPE "${expect}" "${idx}")
  76. string(JSON actual_value GET "${actual}" "${idx}")
  77. string(JSON expect_value GET "${expect}" "${idx}")
  78. check_json_value("${new_path}" "${actual_type}" "${expect_type}" "${actual_value}" "${expect_value}")
  79. endforeach ()
  80. set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
  81. endfunction ()
  82. # Check that two inner objects are the same.
  83. function (check_json_object path actual expect)
  84. string(JSON actual_len LENGTH "${actual}")
  85. string(JSON expect_len LENGTH "${expect}")
  86. set(actual_keys "")
  87. set(expect_keys "")
  88. foreach (idx RANGE "${actual_len}")
  89. if (idx EQUAL actual_len)
  90. break ()
  91. endif ()
  92. string(JSON actual_key MEMBER "${actual}" "${idx}")
  93. list(APPEND actual_keys "${actual_key}")
  94. endforeach ()
  95. foreach (idx RANGE "${expect_len}")
  96. if (idx EQUAL expect_len)
  97. break ()
  98. endif ()
  99. string(JSON expect_key MEMBER "${expect}" "${idx}")
  100. list(APPEND expect_keys "${expect_key}")
  101. endforeach ()
  102. json_placeholders("${expect_keys}" expect_keys_expanded)
  103. set(actual_keys_missed "${actual_keys}")
  104. set(expect_keys_missed "${expect_keys}")
  105. set(common_keys "")
  106. set(expect_keys_stack "${expect_keys}")
  107. while (expect_keys_stack)
  108. list(POP_BACK expect_keys_stack expect_key)
  109. json_placeholders("${expect_key}" expect_key_expanded)
  110. if (expect_key_expanded IN_LIST actual_keys_missed AND
  111. expect_key IN_LIST expect_keys_missed)
  112. list(APPEND common_keys "${expect_key}")
  113. endif ()
  114. list(REMOVE_ITEM actual_keys_missed "${expect_key_expanded}")
  115. list(REMOVE_ITEM expect_keys_missed "${expect_key}")
  116. endwhile ()
  117. if (actual_keys_missed)
  118. string(REPLACE ";" ", " actual_keys_missed_text "${actual_keys_missed}")
  119. list(APPEND RunCMake_TEST_FAILED
  120. "Extra unexpected members at ${path}: ${actual_keys_missed_text}")
  121. endif ()
  122. if (expect_keys_missed)
  123. string(REPLACE ";" ", " expect_keys_missed_text "${expect_keys_missed}")
  124. list(APPEND RunCMake_TEST_FAILED
  125. "Missing expected members at ${path}: ${expect_keys_missed_text}")
  126. endif ()
  127. foreach (key IN LISTS common_keys)
  128. json_placeholders("${key}" key_expanded)
  129. set(new_path "${path}.${key_expanded}")
  130. string(JSON actual_type TYPE "${actual}" "${key_expanded}")
  131. string(JSON expect_type TYPE "${expect}" "${key}")
  132. string(JSON actual_value GET "${actual}" "${key_expanded}")
  133. string(JSON expect_value GET "${expect}" "${key}")
  134. check_json_value("${new_path}" "${actual_type}" "${expect_type}" "${actual_value}" "${expect_value}")
  135. endforeach ()
  136. set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
  137. endfunction ()
  138. # Check that two JSON objects are the same.
  139. function (check_json actual expect)
  140. check_json_object("" "${actual}" "${expect}")
  141. set(RunCMake_TEST_FAILED "${RunCMake_TEST_FAILED}" PARENT_SCOPE)
  142. endfunction ()
  143. cmake_policy(POP)