check-json.cmake 5.4 KB

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