check-json.cmake 5.7 KB

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