@voxgig/sdkgen 4.8.2 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (407) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/dist/action/doctor.d.ts +1 -0
  3. package/dist/action/doctor.js +50 -2
  4. package/dist/action/doctor.js.map +1 -1
  5. package/dist/helpers/naming.js +4 -2
  6. package/dist/helpers/naming.js.map +1 -1
  7. package/dist/tsconfig.tsbuildinfo +1 -1
  8. package/model/sdkgen.aon +21 -0
  9. package/package.json +1 -1
  10. package/project/.sdk/model/feature/secrets.aon +120 -18
  11. package/project/.sdk/model/target/c.aon +10 -0
  12. package/project/.sdk/model/target/clojure.aon +13 -0
  13. package/project/.sdk/model/target/cpp.aon +10 -0
  14. package/project/.sdk/model/target/csharp.aon +9 -0
  15. package/project/.sdk/model/target/dart.aon +10 -0
  16. package/project/.sdk/model/target/elixir.aon +9 -0
  17. package/project/.sdk/model/target/go.aon +13 -0
  18. package/project/.sdk/model/target/java.aon +9 -0
  19. package/project/.sdk/model/target/js.aon +7 -0
  20. package/project/.sdk/model/target/kotlin.aon +9 -0
  21. package/project/.sdk/model/target/lean.aon +17 -0
  22. package/project/.sdk/model/target/lua.aon +8 -0
  23. package/project/.sdk/model/target/ocaml.aon +9 -0
  24. package/project/.sdk/model/target/perl.aon +8 -0
  25. package/project/.sdk/model/target/php.aon +8 -0
  26. package/project/.sdk/model/target/py.aon +13 -0
  27. package/project/.sdk/model/target/rb.aon +8 -0
  28. package/project/.sdk/model/target/rust.aon +10 -0
  29. package/project/.sdk/model/target/scala.aon +21 -2
  30. package/project/.sdk/model/target/swift.aon +18 -0
  31. package/project/.sdk/model/target/ts.aon +13 -0
  32. package/project/.sdk/model/target/zig.aon +9 -0
  33. package/project/.sdk/src/cmp/clojure/Package_clojure.ts +9 -2
  34. package/project/.sdk/src/cmp/cpp/Gitignore_cpp.ts +3 -0
  35. package/project/.sdk/src/cmp/dart/Test_dart.ts +2 -0
  36. package/project/.sdk/src/cmp/elixir/Package_elixir.ts +4 -1
  37. package/project/.sdk/src/cmp/go/Config_go.ts +59 -2
  38. package/project/.sdk/src/cmp/go/Main_go.ts +8 -2
  39. package/project/.sdk/src/cmp/java/Test_java.ts +6 -5
  40. package/project/.sdk/src/cmp/kotlin/Test_kotlin.ts +6 -5
  41. package/project/.sdk/src/cmp/lean/Package_lean.ts +23 -0
  42. package/project/.sdk/src/cmp/lean/ReadmeInstall_lean.ts +1 -0
  43. package/project/.sdk/src/cmp/lean/ReadmeTopTest_lean.ts +1 -0
  44. package/project/.sdk/src/cmp/ocaml/Gitignore_ocaml.ts +1 -0
  45. package/project/.sdk/src/cmp/ocaml/Main_ocaml.ts +7 -3
  46. package/project/.sdk/src/cmp/py/Config_py.ts +82 -1
  47. package/project/.sdk/src/cmp/py/Main_py.ts +44 -0
  48. package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +2 -0
  49. package/project/.sdk/src/cmp/swift/Main_swift.ts +10 -0
  50. package/project/.sdk/src/cmp/swift/Package_swift.ts +13 -1
  51. package/project/.sdk/src/cmp/ts/Config_ts.ts +42 -17
  52. package/project/.sdk/src/cmp/ts/fragment/Config.data.fragment.ts +13 -1
  53. package/project/.sdk/src/cmp/ts/fragment/Config.fragment.ts +13 -1
  54. package/project/.sdk/src/cmp/zig/Package_zig.ts +15 -11
  55. package/project/.sdk/src/cmp/zig/fragment/Entity.fragment.zig +3 -3
  56. package/project/.sdk/src/cmp/zig/fragment/EntityListOp.fragment.zig +3 -3
  57. package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +3 -3
  58. package/project/.sdk/src/cmp/zig/utility_zig.ts +50 -1
  59. package/project/.sdk/tm/c/Makefile +38 -3
  60. package/project/.sdk/tm/c/tests/omni_resolver.h +361 -0
  61. package/project/.sdk/tm/c/tests/omni_smoke_test.c +237 -0
  62. package/project/.sdk/tm/c/tests/primary_corpus_test.c +205 -284
  63. package/project/.sdk/tm/c/tests/struct_corpus_test.c +292 -212
  64. package/project/.sdk/tm/c/tests/vendor/omni/json.c +811 -0
  65. package/project/.sdk/tm/c/tests/vendor/omni/omni.h +240 -0
  66. package/project/.sdk/tm/c/tests/vendor/omni/runner.c +940 -0
  67. package/project/.sdk/tm/c/tests/vendor/omni/util.c +351 -0
  68. package/project/.sdk/tm/c/utility/struct/utility.c +7 -2
  69. package/project/.sdk/tm/clojure/test/sdk/test/omni.clj +401 -0
  70. package/project/.sdk/tm/clojure/test/sdk/test/omni_smoke.clj +81 -0
  71. package/project/.sdk/tm/clojure/test/sdk/test/primary.clj +92 -58
  72. package/project/.sdk/tm/clojure/test/sdk/test/struct_corpus.clj +122 -149
  73. package/project/.sdk/tm/clojure/test/sdk/test_runner.clj +8 -3
  74. package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/json.clj +145 -0
  75. package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/runner.clj +445 -0
  76. package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/util.clj +145 -0
  77. package/project/.sdk/tm/cpp/Makefile +5 -1
  78. package/project/.sdk/tm/cpp/test/omni_resolver.hpp +473 -0
  79. package/project/.sdk/tm/cpp/test/omni_smoke_test.cpp +209 -0
  80. package/project/.sdk/tm/cpp/test/primary_utility_test.cpp +243 -184
  81. package/project/.sdk/tm/cpp/test/runner_support.hpp +68 -181
  82. package/project/.sdk/tm/cpp/test/struct_corpus_test.cpp +183 -56
  83. package/project/.sdk/tm/cpp/test/vendor/omni/json.hpp +406 -0
  84. package/project/.sdk/tm/cpp/test/vendor/omni/omni.hpp +751 -0
  85. package/project/.sdk/tm/cpp/test/vendor/omni/util.hpp +256 -0
  86. package/project/.sdk/tm/cpp/utility/pipeline.hpp +7 -1
  87. package/project/.sdk/tm/csharp/test/OmniResolver.cs +491 -0
  88. package/project/.sdk/tm/csharp/test/OmniSmokeTest.cs +106 -0
  89. package/project/.sdk/tm/csharp/test/PrimaryUtilityTest.cs +299 -316
  90. package/project/.sdk/tm/csharp/test/Runner.cs +104 -269
  91. package/project/.sdk/tm/csharp/test/StructUtilityTest.cs +535 -724
  92. package/project/.sdk/tm/csharp/test/vendor/omni/Runner.cs +864 -0
  93. package/project/.sdk/tm/csharp/test/vendor/omni/Util.cs +347 -0
  94. package/project/.sdk/tm/csharp/utility/MakeSpec.cs +3 -1
  95. package/project/.sdk/tm/csharp/utility/PrepareMethod.cs +6 -1
  96. package/project/.sdk/tm/csharp/utility/struct/Struct.cs +21 -5
  97. package/project/.sdk/tm/dart/test/omni.dart +520 -0
  98. package/project/.sdk/tm/dart/test/omni_smoke_test.dart +143 -0
  99. package/project/.sdk/tm/dart/test/primary_test.dart +86 -28
  100. package/project/.sdk/tm/dart/test/struct_test.dart +438 -11
  101. package/project/.sdk/tm/dart/test/vendor/omni/omni.dart +7 -0
  102. package/project/.sdk/tm/dart/test/vendor/omni/runner.dart +653 -0
  103. package/project/.sdk/tm/dart/test/vendor/omni/util.dart +232 -0
  104. package/project/.sdk/tm/elixir/Makefile +11 -3
  105. package/project/.sdk/tm/elixir/test/omni_smoke_test.exs +117 -0
  106. package/project/.sdk/tm/elixir/test/primary_utility_test.exs +341 -16
  107. package/project/.sdk/tm/elixir/test/struct_corpus_test.exs +554 -9
  108. package/project/.sdk/tm/elixir/test/support/omni.ex +377 -0
  109. package/project/.sdk/tm/elixir/test/vendor/omni/json.ex +122 -0
  110. package/project/.sdk/tm/elixir/test/vendor/omni/runner.ex +623 -0
  111. package/project/.sdk/tm/elixir/test/vendor/omni/util.ex +187 -0
  112. package/project/.sdk/tm/go/core/context.go +32 -16
  113. package/project/.sdk/tm/go/feature/secrets/plugin/capability.go +261 -0
  114. package/project/.sdk/tm/go/feature/secrets/plugin/catalog.go +78 -0
  115. package/project/.sdk/tm/go/feature/secrets/plugin/config.go +652 -0
  116. package/project/.sdk/tm/go/feature/secrets/plugin/depend.go +250 -0
  117. package/project/.sdk/tm/go/feature/secrets/plugin/env.go +194 -0
  118. package/project/.sdk/tm/go/feature/secrets/plugin/export.go +80 -0
  119. package/project/.sdk/tm/go/feature/secrets/plugin/graph.go +238 -0
  120. package/project/.sdk/tm/go/feature/secrets/plugin/host.go +1575 -0
  121. package/project/.sdk/tm/go/feature/secrets/plugin/order.go +248 -0
  122. package/project/.sdk/tm/go/feature/secrets/plugin/point.go +184 -0
  123. package/project/.sdk/tm/go/feature/secrets/plugin/ref.go +123 -0
  124. package/project/.sdk/tm/go/feature/secrets/plugin/resolve.go +79 -0
  125. package/project/.sdk/tm/go/feature/secrets/plugin/types.go +296 -0
  126. package/project/.sdk/tm/go/feature/secrets/plugin/util.go +87 -0
  127. package/project/.sdk/tm/go/feature/secrets/plugin/version.go +161 -0
  128. package/project/.sdk/tm/go/feature/secrets/plugins/aws/aws.go +292 -0
  129. package/project/.sdk/tm/go/feature/secrets/plugins/aws/sigv4.go +201 -0
  130. package/project/.sdk/tm/go/feature/secrets/plugins/azuresecrets/azuresecrets.go +187 -0
  131. package/project/.sdk/tm/go/feature/secrets/plugins/boru/boru.go +184 -0
  132. package/project/.sdk/tm/go/feature/secrets/plugins/doppler/doppler.go +114 -0
  133. package/project/.sdk/tm/go/feature/secrets/plugins/gcpsecrets/gcpsecrets.go +156 -0
  134. package/project/.sdk/tm/go/feature/secrets/plugins/hashicorp/hashicorp.go +208 -0
  135. package/project/.sdk/tm/go/feature/secrets/plugins/httpjson/httpjson.go +241 -0
  136. package/project/.sdk/tm/go/feature/secrets/plugins/infisical/infisical.go +150 -0
  137. package/project/.sdk/tm/go/feature/secrets/plugins/onepassword/onepassword.go +152 -0
  138. package/project/.sdk/tm/go/feature/secrets/plugins/secretspec/secretspec.go +143 -0
  139. package/project/.sdk/tm/go/feature/secrets/sekreto/addr.go +120 -0
  140. package/project/.sdk/tm/go/feature/secrets/sekreto/providers.go +442 -0
  141. package/project/.sdk/tm/go/feature/secrets/sekreto/sekreto.go +714 -0
  142. package/project/.sdk/tm/go/feature/secrets_feature.go +675 -0
  143. package/project/.sdk/tm/go/src/feature/secrets/.gitkeep +0 -0
  144. package/project/.sdk/tm/go/test/feature/secrets/secrets_feature_test.go +799 -0
  145. package/project/.sdk/tm/go/test/omni/omni.go +902 -0
  146. package/project/.sdk/tm/go/test/omni/util.go +381 -0
  147. package/project/.sdk/tm/go/test/omniresolver_test.go +748 -0
  148. package/project/.sdk/tm/go/test/omnismoke_test.go +112 -0
  149. package/project/.sdk/tm/go/test/primary_utility_test.go +123 -191
  150. package/project/.sdk/tm/go/test/struct_utility_test.go +323 -16
  151. package/project/.sdk/tm/go/test/testsupport_test.go +294 -0
  152. package/project/.sdk/tm/go/utility/make_options.go +8 -1
  153. package/project/.sdk/tm/go/utility/prepare_method.go +5 -1
  154. package/project/.sdk/tm/go/utility/struct/voxgigstruct.go +2 -2
  155. package/project/.sdk/tm/java/test/OmniResolver.java +355 -0
  156. package/project/.sdk/tm/java/test/OmniSmokeTest.java +99 -0
  157. package/project/.sdk/tm/java/test/PrimaryUtilityTest.java +254 -280
  158. package/project/.sdk/tm/java/test/RunnerSupport.java +9 -194
  159. package/project/.sdk/tm/java/test/StructCorpusTest.java +119 -42
  160. package/project/.sdk/tm/java/test/vendor/omni/Json.java +287 -0
  161. package/project/.sdk/tm/java/test/vendor/omni/Runner.java +851 -0
  162. package/project/.sdk/tm/java/test/vendor/omni/Util.java +322 -0
  163. package/project/.sdk/tm/java/utility/MakeSpec.java +3 -1
  164. package/project/.sdk/tm/java/utility/PrepareMethod.java +5 -5
  165. package/project/.sdk/tm/java/utility/struct/Struct.java +17 -4
  166. package/project/.sdk/tm/js/src/utility/StructUtility.js +3 -3
  167. package/project/.sdk/tm/js/test/omni.js +251 -0
  168. package/project/.sdk/tm/js/test/omni.test.js +105 -0
  169. package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +6 -2
  170. package/project/.sdk/tm/js/test/utility/StructUtility.test.js +27 -2
  171. package/project/.sdk/tm/js/test/vendor/omni/index.js +77 -0
  172. package/project/.sdk/tm/js/test/vendor/omni/runner.js +628 -0
  173. package/project/.sdk/tm/js/test/vendor/omni/util.js +229 -0
  174. package/project/.sdk/tm/kotlin/core/Utility.kt +1 -1
  175. package/project/.sdk/tm/kotlin/test/OmniResolver.kt +343 -0
  176. package/project/.sdk/tm/kotlin/test/OmniSmokeTest.kt +100 -0
  177. package/project/.sdk/tm/kotlin/test/PrimaryUtilityTest.kt +244 -262
  178. package/project/.sdk/tm/kotlin/test/RunnerSupport.kt +9 -178
  179. package/project/.sdk/tm/kotlin/test/StructCorpusTest.kt +121 -32
  180. package/project/.sdk/tm/kotlin/test/vendor/omni/Json.kt +264 -0
  181. package/project/.sdk/tm/kotlin/test/vendor/omni/Runner.kt +615 -0
  182. package/project/.sdk/tm/kotlin/test/vendor/omni/Util.kt +139 -0
  183. package/project/.sdk/tm/kotlin/utility/MakeSpecUrl.kt +6 -3
  184. package/project/.sdk/tm/kotlin/utility/Prepare.kt +6 -6
  185. package/project/.sdk/tm/kotlin/utility/struct/Struct.kt +18 -2
  186. package/project/.sdk/tm/lean/Makefile +12 -5
  187. package/project/.sdk/tm/lean/src/SdkUtility.lean +14 -1
  188. package/project/.sdk/tm/lean/test/OmniResolver.lean +358 -0
  189. package/project/.sdk/tm/lean/test/OmniSmoke.lean +174 -0
  190. package/project/.sdk/tm/lean/test/StructCorpus.lean +245 -574
  191. package/project/.sdk/tm/lean/test/TPrimaryUtility.lean +155 -291
  192. package/project/.sdk/tm/lean/test/vendor/omni/Omni.lean +997 -0
  193. package/project/.sdk/tm/lua/test/omni.lua +456 -0
  194. package/project/.sdk/tm/lua/test/omni_smoke_test.lua +103 -0
  195. package/project/.sdk/tm/lua/test/primary_utility_test.lua +250 -509
  196. package/project/.sdk/tm/lua/test/struct_utility_test.lua +161 -70
  197. package/project/.sdk/tm/lua/test/vendor/omni/json.lua +268 -0
  198. package/project/.sdk/tm/lua/test/vendor/omni/regex.lua +385 -0
  199. package/project/.sdk/tm/lua/test/vendor/omni/runner.lua +641 -0
  200. package/project/.sdk/tm/lua/test/vendor/omni/util.lua +282 -0
  201. package/project/.sdk/tm/lua/utility/prepare_method.lua +5 -1
  202. package/project/.sdk/tm/lua/utility/struct/regex.lua +663 -0
  203. package/project/.sdk/tm/lua/utility/struct/struct.lua +660 -420
  204. package/project/.sdk/tm/ocaml/Makefile +37 -12
  205. package/project/.sdk/tm/ocaml/test/omni_resolver.ml +284 -0
  206. package/project/.sdk/tm/ocaml/test/omni_smoke_test.ml +169 -0
  207. package/project/.sdk/tm/ocaml/test/primary_utility_test.ml +84 -100
  208. package/project/.sdk/tm/ocaml/test/struct_corpus.ml +225 -201
  209. package/project/.sdk/tm/ocaml/test/vendor/omni/omni.ml +1157 -0
  210. package/project/.sdk/tm/perl/lib/Voxgig/Struct.pm +88 -12
  211. package/project/.sdk/tm/perl/t/omni.pm +647 -0
  212. package/project/.sdk/tm/perl/t/omni_smoke.t +87 -0
  213. package/project/.sdk/tm/perl/t/primary_utility.t +189 -487
  214. package/project/.sdk/tm/perl/t/struct_utility.t +455 -389
  215. package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni/Runner.pm +649 -0
  216. package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni/Util.pm +253 -0
  217. package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni.pm +24 -0
  218. package/project/.sdk/tm/perl/utility/prepare_method.pm +7 -2
  219. package/project/.sdk/tm/php/test/Omni.php +691 -0
  220. package/project/.sdk/tm/php/test/OmniSmokeTest.php +93 -0
  221. package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +210 -571
  222. package/project/.sdk/tm/php/test/StructUtilityTest.php +320 -342
  223. package/project/.sdk/tm/php/test/vendor/omni/Runner.php +644 -0
  224. package/project/.sdk/tm/php/test/vendor/omni/Util.php +283 -0
  225. package/project/.sdk/tm/php/utility/MakeSpec.php +10 -3
  226. package/project/.sdk/tm/php/utility/PrepareBody.php +7 -1
  227. package/project/.sdk/tm/php/utility/PrepareMethod.php +6 -2
  228. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/__init__.py +36 -0
  229. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/capability.py +141 -0
  230. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/catalog.py +50 -0
  231. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/config.py +333 -0
  232. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/depend.py +198 -0
  233. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/env.py +147 -0
  234. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/export.py +52 -0
  235. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/graph.py +139 -0
  236. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/host.py +1053 -0
  237. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/order.py +171 -0
  238. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/point.py +95 -0
  239. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/ref.py +116 -0
  240. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/resolve.py +59 -0
  241. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/types.py +87 -0
  242. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/version.py +112 -0
  243. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/__init__.py +76 -0
  244. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/addr.py +116 -0
  245. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/aws.py +192 -0
  246. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/azuresecrets.py +120 -0
  247. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/boru.py +140 -0
  248. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/doppler.py +62 -0
  249. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/gcpsecrets.py +101 -0
  250. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/hashicorp.py +151 -0
  251. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/httpjson.py +115 -0
  252. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/infisical.py +90 -0
  253. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/onepassword.py +101 -0
  254. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/secretspec.py +119 -0
  255. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/sigv4.py +125 -0
  256. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/providers.py +211 -0
  257. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/sekreto.py +475 -0
  258. package/project/.sdk/tm/py/pkg/feature/secrets_feature.py +467 -0
  259. package/project/.sdk/tm/py/pkg/utility/prepare_method.py +5 -1
  260. package/project/.sdk/tm/py/pkg/utility/voxgig_struct/__init__.py +0 -2
  261. package/project/.sdk/tm/py/pkg/utility/voxgig_struct/voxgig_struct.py +780 -529
  262. package/project/.sdk/tm/py/src/feature/secrets/.gitkeep +0 -0
  263. package/project/.sdk/tm/py/test/feature/__init__.py +0 -0
  264. package/project/.sdk/tm/py/test/feature/secrets/__init__.py +0 -0
  265. package/project/.sdk/tm/py/test/feature/secrets/test_secrets.py +337 -0
  266. package/project/.sdk/tm/py/test/omni.py +415 -0
  267. package/project/.sdk/tm/py/test/test_omni_smoke.py +74 -0
  268. package/project/.sdk/tm/py/test/test_primary_utility.py +144 -668
  269. package/project/.sdk/tm/py/test/test_struct_utility.py +74 -27
  270. package/project/.sdk/tm/py/test/voxgig_omni/__init__.py +62 -0
  271. package/project/.sdk/tm/py/test/voxgig_omni/runner.py +580 -0
  272. package/project/.sdk/tm/py/test/voxgig_omni/util.py +252 -0
  273. package/project/.sdk/tm/rb/test/omni.rb +505 -0
  274. package/project/.sdk/tm/rb/test/omni_smoke_test.rb +72 -0
  275. package/project/.sdk/tm/rb/test/primary_utility_test.rb +174 -560
  276. package/project/.sdk/tm/rb/test/struct_utility_test.rb +13 -7
  277. package/project/.sdk/tm/rb/test/vendor/omni/runner.rb +493 -0
  278. package/project/.sdk/tm/rb/test/vendor/omni/util.rb +199 -0
  279. package/project/.sdk/tm/rb/test/vendor/omni/voxgig_omni.rb +15 -0
  280. package/project/.sdk/tm/rb/utility/prepare_method.rb +5 -1
  281. package/project/.sdk/tm/rust/tests/common/mod.rs +19 -242
  282. package/project/.sdk/tm/rust/tests/omni_resolver/mod.rs +888 -0
  283. package/project/.sdk/tm/rust/tests/omni_smoke_test.rs +286 -0
  284. package/project/.sdk/tm/rust/tests/primary_utility_test.rs +318 -312
  285. package/project/.sdk/tm/rust/tests/struct_utility_test.rs +66 -28
  286. package/project/.sdk/tm/rust/tests/vendor/omni/json.rs +412 -0
  287. package/project/.sdk/tm/rust/tests/vendor/omni/mod.rs +38 -0
  288. package/project/.sdk/tm/rust/tests/vendor/omni/regex.rs +392 -0
  289. package/project/.sdk/tm/rust/tests/vendor/omni/runner.rs +1001 -0
  290. package/project/.sdk/tm/rust/tests/vendor/omni/util.rs +161 -0
  291. package/project/.sdk/tm/rust/utility/prepare_method.rs +5 -1
  292. package/project/.sdk/tm/scala/Makefile +16 -6
  293. package/project/.sdk/tm/scala/sdktest/OmniResolver.scala +497 -0
  294. package/project/.sdk/tm/scala/sdktest/OmniSmoke.scala +192 -0
  295. package/project/.sdk/tm/scala/sdktest/PrimaryCorpus.scala +47 -19
  296. package/project/.sdk/tm/scala/sdktest/StructCorpus.scala +0 -0
  297. package/project/.sdk/tm/scala/sdktest/vendor/omni/Json.scala +229 -0
  298. package/project/.sdk/tm/scala/sdktest/vendor/omni/Runner.scala +552 -0
  299. package/project/.sdk/tm/scala/sdktest/vendor/omni/Util.scala +104 -0
  300. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Constants.swift +10 -0
  301. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Inject.swift +28 -5
  302. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Injection.swift +5 -1
  303. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Minor.swift +4 -1
  304. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Validate.swift +15 -5
  305. package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Prepare.swift +6 -1
  306. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/OmniResolver.swift +474 -0
  307. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/OmniSmokeTest.swift +107 -0
  308. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/PrimaryUtilityTest.swift +141 -178
  309. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/Runner.swift +17 -113
  310. package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/StructUtilityTest.swift +295 -446
  311. package/project/.sdk/tm/swift/Tests/vendor/omni/Json.swift +364 -0
  312. package/project/.sdk/tm/swift/Tests/vendor/omni/Runner.swift +730 -0
  313. package/project/.sdk/tm/swift/Tests/vendor/omni/Util.swift +162 -0
  314. package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +7 -0
  315. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Capability.ts +148 -0
  316. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Catalog.ts +55 -0
  317. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Config.ts +344 -0
  318. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Depend.ts +205 -0
  319. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Env.ts +138 -0
  320. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Export.ts +46 -0
  321. package/project/.sdk/tm/ts/src/feature/secrets/plugin/FeatureHost.ts +349 -0
  322. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Graph.ts +181 -0
  323. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Host.ts +1132 -0
  324. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Order.ts +177 -0
  325. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Point.ts +119 -0
  326. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Ref.ts +102 -0
  327. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Resolve.ts +61 -0
  328. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Types.ts +112 -0
  329. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Version.ts +100 -0
  330. package/project/.sdk/tm/ts/src/feature/secrets/plugin/index.ts +37 -0
  331. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sekreto.ts +163 -30
  332. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/index.ts +27 -22
  333. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/aws.ts +26 -36
  334. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/azuresecrets.ts +19 -21
  335. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/boru.ts +36 -17
  336. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/doppler.ts +14 -21
  337. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/gcpsecrets.ts +27 -27
  338. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/hashicorp.ts +25 -39
  339. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/httpjson.ts +99 -0
  340. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/infisical.ts +14 -16
  341. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/onepassword.ts +15 -22
  342. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/secretspec.ts +98 -0
  343. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{Sigv4.ts → plugins/sigv4.ts} +7 -6
  344. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/addr.ts +97 -23
  345. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/builtin.ts +37 -0
  346. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/dotenv.ts +4 -17
  347. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/env.ts +4 -16
  348. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/file.ts +11 -25
  349. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/memory.ts +6 -23
  350. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/support.ts +106 -39
  351. package/project/.sdk/tm/ts/src/utility/StructUtility.ts +3 -3
  352. package/project/.sdk/tm/ts/test/omni.ts +104 -32
  353. package/project/.sdk/tm/ts/test/utility/StructUtility.test.ts +27 -0
  354. package/project/.sdk/tm/ts/test/vendor/omni/Runner.ts +32 -5
  355. package/project/.sdk/tm/ts/test/vendor/omni/Util.ts +2 -2
  356. package/project/.sdk/tm/ts/test/vendor/omni/index.ts +2 -2
  357. package/project/.sdk/tm/zig/Makefile +15 -1
  358. package/project/.sdk/tm/zig/build.zig +23 -5
  359. package/project/.sdk/tm/zig/core/helpers.zig +52 -11
  360. package/project/.sdk/tm/zig/core/mem.zig +17 -1
  361. package/project/.sdk/tm/zig/core/utility.zig +23 -19
  362. package/project/.sdk/tm/zig/feature/audit.zig +2 -2
  363. package/project/.sdk/tm/zig/feature/cache.zig +2 -2
  364. package/project/.sdk/tm/zig/feature/debug.zig +5 -5
  365. package/project/.sdk/tm/zig/feature/netsim.zig +2 -2
  366. package/project/.sdk/tm/zig/feature/paging.zig +2 -2
  367. package/project/.sdk/tm/zig/feature/proxy.zig +15 -8
  368. package/project/.sdk/tm/zig/feature/streaming.zig +5 -5
  369. package/project/.sdk/tm/zig/feature/support.zig +3 -3
  370. package/project/.sdk/tm/zig/feature/telemetry.zig +5 -5
  371. package/project/.sdk/tm/zig/feature/test.zig +10 -5
  372. package/project/.sdk/tm/zig/test/fh.zig +10 -10
  373. package/project/.sdk/tm/zig/test/gotcha_test.zig +5 -5
  374. package/project/.sdk/tm/zig/test/omniresolver.zig +515 -0
  375. package/project/.sdk/tm/zig/test/omnismoke_test.zig +284 -0
  376. package/project/.sdk/tm/zig/test/pipeline_test.zig +8 -8
  377. package/project/.sdk/tm/zig/test/primary_utility_test.zig +145 -155
  378. package/project/.sdk/tm/zig/test/struct_corpus.zig +264 -187
  379. package/project/.sdk/tm/zig/test/vendor/omni/omni.zig +1314 -0
  380. package/project/.sdk/tm/zig/test/vendor/omni/regex.zig +446 -0
  381. package/project/.sdk/tm/zig/utility/voxgigstruct/regex.zig +7 -4
  382. package/project/.sdk/tm/zig/utility/voxgigstruct/struct.zig +356 -157
  383. package/project/sdkgen-package.json +1 -1
  384. package/src/action/doctor.ts +66 -2
  385. package/src/helpers/naming.ts +4 -2
  386. package/project/.sdk/tm/c/tests/runner.h +0 -274
  387. package/project/.sdk/tm/cpp/test/struct_runner.hpp +0 -314
  388. package/project/.sdk/tm/csharp/test/StructRunner.cs +0 -276
  389. package/project/.sdk/tm/dart/test/runner.dart +0 -406
  390. package/project/.sdk/tm/dart/test/struct_corpus.dart +0 -531
  391. package/project/.sdk/tm/elixir/test/support/struct_corpus.ex +0 -1088
  392. package/project/.sdk/tm/go/test/runner_test.go +0 -629
  393. package/project/.sdk/tm/go/test/struct_runner_test.go +0 -1094
  394. package/project/.sdk/tm/java/test/StructRunner.java +0 -281
  395. package/project/.sdk/tm/js/test/runner.js +0 -387
  396. package/project/.sdk/tm/kotlin/test/StructRunner.kt +0 -177
  397. package/project/.sdk/tm/lua/test/struct_runner.lua +0 -602
  398. package/project/.sdk/tm/ocaml/test/corpus_runner.ml +0 -185
  399. package/project/.sdk/tm/perl/t/struct_runner.pm +0 -275
  400. package/project/.sdk/tm/php/test/StructRunner.php +0 -275
  401. package/project/.sdk/tm/py/test/struct_runner.py +0 -411
  402. package/project/.sdk/tm/rb/test/struct_runner.rb +0 -309
  403. package/project/.sdk/tm/rust/tests/struct_runner/mod.rs +0 -424
  404. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/Registry.ts +0 -90
  405. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/http.ts +0 -66
  406. package/project/.sdk/tm/ts/test/vendor/omni/compat.ts +0 -188
  407. package/project/.sdk/tm/zig/test/struct_runner.zig +0 -464
@@ -0,0 +1,1157 @@
1
+ (* VENDORED: @voxgig/omni sdk-20260907-0029-0 (ocaml/src/omni.ml) *)
2
+ (* Source: https://github.com/voxgig/omni @ 274708cc2d12b21707d975543953f845f8444be0 [tag: sdk-20260907-0029-0] *)
3
+ (* License: MIT (c) voxgig - see repository LICENSE. Do not edit: resync from upstream. *)
4
+ (* Omni: the shared multi-language test runner (OCaml port).
5
+
6
+ A test spec is plain JSON. The same spec file drives the same tests in
7
+ every language that ships an omni port.
8
+
9
+ Port of the canonical TypeScript implementation
10
+ (typescript/src/Runner.ts). Behaviour must match, case for case.
11
+
12
+ Self-contained by design: the runner carries its own JSON value model,
13
+ parser and regex engine, so that it can test *any* library - including
14
+ one that provides those same operations - and adds no dependencies. *)
15
+
16
+ (* ---- the JSON value model ------------------------------------------ *)
17
+
18
+ (* `Absent` is the marker for "no value at all", as distinct from `Null`. *)
19
+ type json =
20
+ | Absent
21
+ | Null
22
+ | Bool of bool
23
+ | Num of float
24
+ | Str of string
25
+ | JList of json list
26
+ | JMap of (string * json) list
27
+
28
+ let nullmark = "__NULL__" (* Value is JSON null. *)
29
+ let undefmark = "__UNDEF__" (* Value is not present. *)
30
+ let existsmark = "__EXISTS__" (* Value exists (not undefined). *)
31
+
32
+ let ismap = function JMap _ -> true | _ -> false
33
+ let islist = function JList _ -> true | _ -> false
34
+ let isnode val_ = ismap val_ || islist val_
35
+ let isabsent = function Absent -> true | _ -> false
36
+ let isnull = function Null -> true | _ -> false
37
+ let isnone val_ = isabsent val_ || isnull val_
38
+ let isnum = function Num _ -> true | _ -> false
39
+ let isstr = function Str _ -> true | _ -> false
40
+
41
+ let asnum = function Num v -> Some v | _ -> None
42
+ let asstr = function Str v -> Some v | _ -> None
43
+ let aslist = function JList v -> Some v | _ -> None
44
+ let asmap = function JMap v -> Some v | _ -> None
45
+
46
+ (* Read a map entry. Returns Absent when missing. *)
47
+ let jget val_ key =
48
+ match val_ with
49
+ | JMap entries -> (try List.assoc key entries with Not_found -> Absent)
50
+ | _ -> Absent
51
+
52
+ (* Is a map key present at all (even with a null value)? *)
53
+ let jhas val_ key =
54
+ match val_ with JMap entries -> List.mem_assoc key entries | _ -> false
55
+
56
+ (* A copy of a map with one entry set (no-op for non-maps). *)
57
+ let jset val_ key entry =
58
+ match val_ with
59
+ | JMap entries ->
60
+ if List.mem_assoc key entries then
61
+ JMap (List.map (fun (k, e) -> if k = key then (k, entry) else (k, e)) entries)
62
+ else JMap (entries @ [ (key, entry) ])
63
+ | other -> other
64
+
65
+ (* ---- errors -------------------------------------------------------- *)
66
+
67
+ (* A test failure (or a malformed spec). Distinct from an exception raised
68
+ by the subject under test, which is a candidate for an `err`
69
+ expectation. *)
70
+ exception Omni_error of string
71
+
72
+ let omni_error message = Omni_error message
73
+
74
+ (* ---- number and string rendering ----------------------------------- *)
75
+
76
+ (* Render a number the same way in every port: 5.0 prints as 5. *)
77
+ let numstr value =
78
+ if Float.is_nan value || Float.is_integer value = false then
79
+ if Float.is_nan value || value = Float.infinity || value = Float.neg_infinity then "null"
80
+ else Printf.sprintf "%.17g" value
81
+ else if Float.abs value < 9007199254740992.0 then Printf.sprintf "%.0f" value
82
+ else Printf.sprintf "%.17g" value
83
+
84
+ (* Render a string as a JSON string literal. *)
85
+ let quote value =
86
+ let buf = Buffer.create (String.length value + 2) in
87
+ Buffer.add_char buf '"';
88
+ String.iter
89
+ (fun ch ->
90
+ match ch with
91
+ | '"' -> Buffer.add_string buf "\\\""
92
+ | '\\' -> Buffer.add_string buf "\\\\"
93
+ | '\n' -> Buffer.add_string buf "\\n"
94
+ | '\r' -> Buffer.add_string buf "\\r"
95
+ | '\t' -> Buffer.add_string buf "\\t"
96
+ | _ ->
97
+ if Char.code ch < 0x20 then Buffer.add_string buf (Printf.sprintf "\\u%04x" (Char.code ch))
98
+ else Buffer.add_char buf ch)
99
+ value;
100
+ Buffer.add_char buf '"';
101
+ Buffer.contents buf
102
+
103
+ (* Compact JSON text with map keys sorted, identical in every port. *)
104
+ let rec jsonstr value =
105
+ match value with
106
+ | Absent -> "undefined"
107
+ | Null -> "null"
108
+ | Bool flag -> if flag then "true" else "false"
109
+ | Num entry -> numstr entry
110
+ | Str text -> quote text
111
+ | JList entries -> "[" ^ String.concat "," (List.map jsonstr entries) ^ "]"
112
+ | JMap entries ->
113
+ let sorted = List.sort (fun (a, _) (b, _) -> compare a b) entries in
114
+ "{" ^ String.concat "," (List.map (fun (key, e) -> quote key ^ ":" ^ jsonstr e) sorted) ^ "}"
115
+
116
+ (* Strings verbatim, everything else as compact JSON. *)
117
+ let stringify value = match value with Str text -> text | other -> jsonstr other
118
+
119
+ (* Render a path as a dotted string. *)
120
+ let pathify path = String.concat "." path
121
+
122
+ (* ---- json parser --------------------------------------------------- *)
123
+
124
+ let parse text =
125
+ let len = String.length text in
126
+ let pos = ref 0 in
127
+
128
+ let fail reason = raise (Omni_error (Printf.sprintf "omni: %s at %d" reason !pos)) in
129
+
130
+ let skipws () =
131
+ while
132
+ !pos < len
133
+ && (match text.[!pos] with ' ' | '\t' | '\n' | '\r' -> true | _ -> false)
134
+ do
135
+ incr pos
136
+ done
137
+ in
138
+
139
+ let word want value =
140
+ let wlen = String.length want in
141
+ if !pos + wlen <= len && String.sub text !pos wlen = want then (
142
+ pos := !pos + wlen;
143
+ value)
144
+ else fail "bad JSON literal"
145
+ in
146
+
147
+ let parsestring () =
148
+ if !pos >= len || text.[!pos] <> '"' then fail "expected string";
149
+ incr pos;
150
+ let buf = Buffer.create 16 in
151
+ let result = ref None in
152
+ while !result = None do
153
+ if !pos >= len then fail "unterminated JSON string";
154
+ let ch = text.[!pos] in
155
+ incr pos;
156
+ if ch = '"' then result := Some (Buffer.contents buf)
157
+ else if ch <> '\\' then Buffer.add_char buf ch
158
+ else begin
159
+ if !pos >= len then fail "unterminated JSON string";
160
+ let escape = text.[!pos] in
161
+ incr pos;
162
+ match escape with
163
+ | '"' -> Buffer.add_char buf '"'
164
+ | '\\' -> Buffer.add_char buf '\\'
165
+ | '/' -> Buffer.add_char buf '/'
166
+ | 'b' -> Buffer.add_char buf '\b'
167
+ | 'f' -> Buffer.add_char buf '\012'
168
+ | 'n' -> Buffer.add_char buf '\n'
169
+ | 'r' -> Buffer.add_char buf '\r'
170
+ | 't' -> Buffer.add_char buf '\t'
171
+ | 'u' ->
172
+ if !pos + 4 > len then fail "bad JSON unicode escape";
173
+ (* Exactly four hex digits: int_of_string would accept '_'
174
+ separators and raise Failure on other junk. *)
175
+ let hexdigit ch =
176
+ match ch with
177
+ | '0' .. '9' -> Char.code ch - Char.code '0'
178
+ | 'a' .. 'f' -> Char.code ch - Char.code 'a' + 10
179
+ | 'A' .. 'F' -> Char.code ch - Char.code 'A' + 10
180
+ | _ -> fail "bad JSON unicode escape"
181
+ in
182
+ let code = ref 0 in
183
+ for step = 0 to 3 do
184
+ code := (!code * 16) + hexdigit text.[!pos + step]
185
+ done;
186
+ let code = !code in
187
+ pos := !pos + 4;
188
+ (* UTF-8 encode. *)
189
+ if code < 0x80 then Buffer.add_char buf (Char.chr code)
190
+ else if code < 0x800 then begin
191
+ Buffer.add_char buf (Char.chr (0xC0 lor (code lsr 6)));
192
+ Buffer.add_char buf (Char.chr (0x80 lor (code land 0x3F)))
193
+ end
194
+ else begin
195
+ Buffer.add_char buf (Char.chr (0xE0 lor (code lsr 12)));
196
+ Buffer.add_char buf (Char.chr (0x80 lor ((code lsr 6) land 0x3F)));
197
+ Buffer.add_char buf (Char.chr (0x80 lor (code land 0x3F)))
198
+ end
199
+ | _ -> fail "bad JSON escape"
200
+ end
201
+ done;
202
+ match !result with Some text -> text | None -> fail "unterminated JSON string"
203
+ in
204
+
205
+ let parsenumber () =
206
+ let start = !pos in
207
+ if !pos < len && (text.[!pos] = '-' || text.[!pos] = '+') then incr pos;
208
+ while
209
+ !pos < len
210
+ && (match text.[!pos] with
211
+ | '0' .. '9' | '.' | 'e' | 'E' | '-' | '+' -> true
212
+ | _ -> false)
213
+ do
214
+ incr pos
215
+ done;
216
+ let span = String.sub text start (!pos - start) in
217
+ match float_of_string_opt span with
218
+ | Some value -> Num value
219
+ | None -> fail ("bad JSON number [" ^ span ^ "]")
220
+ in
221
+
222
+ let rec parsevalue () =
223
+ if !pos >= len then fail "unexpected end of JSON";
224
+ match text.[!pos] with
225
+ | '{' -> parsemap ()
226
+ | '[' -> parselist ()
227
+ | '"' -> Str (parsestring ())
228
+ | 't' -> word "true" (Bool true)
229
+ | 'f' -> word "false" (Bool false)
230
+ | 'n' -> word "null" Null
231
+ | _ -> parsenumber ()
232
+ and parsemap () =
233
+ incr pos;
234
+ skipws ();
235
+ if !pos < len && text.[!pos] = '}' then begin
236
+ incr pos;
237
+ JMap []
238
+ end
239
+ else begin
240
+ let entries = ref [] in
241
+ let running = ref true in
242
+ while !running do
243
+ skipws ();
244
+ let key = parsestring () in
245
+ skipws ();
246
+ if !pos >= len || text.[!pos] <> ':' then fail "expected ':'";
247
+ incr pos;
248
+ skipws ();
249
+ let value = parsevalue () in
250
+ (* A duplicate key overrides the earlier value (last wins), as in
251
+ the canonical implementation. *)
252
+ if List.mem_assoc key !entries then
253
+ entries := List.map (fun (k, e) -> if k = key then (k, value) else (k, e)) !entries
254
+ else entries := !entries @ [ (key, value) ];
255
+ skipws ();
256
+ if !pos >= len then fail "unterminated JSON object";
257
+ if text.[!pos] = ',' then incr pos
258
+ else if text.[!pos] = '}' then begin
259
+ incr pos;
260
+ running := false
261
+ end
262
+ else fail "expected ',' or '}'"
263
+ done;
264
+ JMap !entries
265
+ end
266
+ and parselist () =
267
+ incr pos;
268
+ skipws ();
269
+ if !pos < len && text.[!pos] = ']' then begin
270
+ incr pos;
271
+ JList []
272
+ end
273
+ else begin
274
+ let entries = ref [] in
275
+ let running = ref true in
276
+ while !running do
277
+ skipws ();
278
+ entries := !entries @ [ parsevalue () ];
279
+ skipws ();
280
+ if !pos >= len then fail "unterminated JSON array";
281
+ if text.[!pos] = ',' then incr pos
282
+ else if text.[!pos] = ']' then begin
283
+ incr pos;
284
+ running := false
285
+ end
286
+ else fail "expected ',' or ']'"
287
+ done;
288
+ JList !entries
289
+ end
290
+ in
291
+
292
+ skipws ();
293
+ let value = parsevalue () in
294
+ skipws ();
295
+ if !pos < len then fail "trailing JSON content";
296
+ value
297
+
298
+ (* ---- util ---------------------------------------------------------- *)
299
+
300
+ (* Deep copy a JSON value (the value model is immutable). *)
301
+ let clone value = value
302
+
303
+ (* Read a value by path. Returns Absent when any step is missing. *)
304
+ let rec getpath value path =
305
+ match path with
306
+ | [] -> value
307
+ | part :: rest ->
308
+ let next =
309
+ match value with
310
+ | JList entries -> (
311
+ match int_of_string_opt part with
312
+ | Some index when index >= 0 && index < List.length entries -> List.nth entries index
313
+ | _ -> Absent)
314
+ | JMap _ -> jget value part
315
+ | _ -> Absent
316
+ in
317
+ if isabsent next then Absent else getpath next rest
318
+
319
+ (* Depth-first walk: children first, then the containing node. *)
320
+ let rec walk value apply path =
321
+ let next =
322
+ match value with
323
+ | JList entries ->
324
+ JList (List.mapi (fun index entry -> walk entry apply (path @ [ string_of_int index ])) entries)
325
+ | JMap entries -> JMap (List.map (fun (key, entry) -> (key, walk entry apply (path @ [ key ]))) entries)
326
+ | other -> other
327
+ in
328
+ apply next path
329
+
330
+ (* Deep structural equality: numbers by value, bools never numbers. *)
331
+ let rec deepequal a b =
332
+ match (a, b) with
333
+ | Absent, Absent -> true
334
+ | Null, Null -> true
335
+ | Bool x, Bool y -> x = y
336
+ | Num x, Num y -> x = y || (Float.is_nan x && Float.is_nan y)
337
+ | Str x, Str y -> x = y
338
+ | JList x, JList y -> List.length x = List.length y && List.for_all2 deepequal x y
339
+ | JMap x, JMap y ->
340
+ List.length x = List.length y
341
+ && List.for_all
342
+ (fun (key, entry) -> List.mem_assoc key y && deepequal entry (List.assoc key y))
343
+ x
344
+ | _ -> false
345
+
346
+ (* ---- regex engine --------------------------------------------------- *)
347
+
348
+ (* Omni specs match error messages with `/pattern/` expectations, so every
349
+ port needs a regex. OCaml's Str has a different dialect, so omni carries
350
+ this engine, a direct port of the Rust one (rust/src/regex.rs). *)
351
+
352
+ type reitem =
353
+ | IChar of char
354
+ | IRange of char * char
355
+ | IDigit of bool
356
+ | IWord of bool
357
+ | ISpace of bool
358
+
359
+ type renode =
360
+ | RChar of char
361
+ | RAny
362
+ | RClass of reitem list * bool
363
+ | RStart
364
+ | REnd
365
+ | RSeq of renode list
366
+ | RAlt of renode list
367
+ | RRepeat of renode * int * int option * bool
368
+
369
+ exception Regex_error of string
370
+
371
+ let regex_parse pattern =
372
+ let len = String.length pattern in
373
+ let pos = ref 0 in
374
+
375
+ let escapenode escape =
376
+ match escape with
377
+ | 'd' -> RClass ([ IDigit false ], false)
378
+ | 'D' -> RClass ([ IDigit false ], true)
379
+ | 'w' -> RClass ([ IWord false ], false)
380
+ | 'W' -> RClass ([ IWord false ], true)
381
+ | 's' -> RClass ([ ISpace false ], false)
382
+ | 'S' -> RClass ([ ISpace false ], true)
383
+ | 'n' -> RChar '\n'
384
+ | 'r' -> RChar '\r'
385
+ | 't' -> RChar '\t'
386
+ | other -> RChar other
387
+ in
388
+
389
+ let parseclass () =
390
+ incr pos;
391
+ let negated = !pos < len && pattern.[!pos] = '^' in
392
+ if negated then incr pos;
393
+ let items = ref [] in
394
+ let first = ref true in
395
+ let result = ref None in
396
+ while !result = None do
397
+ if !pos >= len then raise (Regex_error "omni: unterminated regex class");
398
+ let ch = pattern.[!pos] in
399
+ if ch = ']' && not !first then begin
400
+ incr pos;
401
+ result := Some (RClass (!items, negated))
402
+ end
403
+ else begin
404
+ first := false;
405
+ if ch = '\\' && !pos + 1 < len then begin
406
+ let escape = pattern.[!pos + 1] in
407
+ pos := !pos + 2;
408
+ items :=
409
+ !items
410
+ @ [ (match escape with
411
+ | 'd' -> IDigit false
412
+ | 'w' -> IWord false
413
+ | 's' -> ISpace false
414
+ | 'n' -> IChar '\n'
415
+ | 'r' -> IChar '\r'
416
+ | 't' -> IChar '\t'
417
+ | other -> IChar other) ]
418
+ end
419
+ else begin
420
+ incr pos;
421
+ if !pos + 1 < len && pattern.[!pos] = '-' && pattern.[!pos + 1] <> ']' then begin
422
+ items := !items @ [ IRange (ch, pattern.[!pos + 1]) ];
423
+ pos := !pos + 2
424
+ end
425
+ else items := !items @ [ IChar ch ]
426
+ end
427
+ end
428
+ done;
429
+ match !result with Some node -> node | None -> raise (Regex_error "omni: bad regex class")
430
+ in
431
+
432
+ let parsecount () =
433
+ let start = !pos in
434
+ incr pos;
435
+ let digits = Buffer.create 4 in
436
+ while !pos < len && pattern.[!pos] >= '0' && pattern.[!pos] <= '9' do
437
+ Buffer.add_char digits pattern.[!pos];
438
+ incr pos
439
+ done;
440
+ if Buffer.length digits = 0 then begin
441
+ pos := start;
442
+ None
443
+ end
444
+ else begin
445
+ (* A count too large for an int degrades to a literal `{`, rather
446
+ than leaking a Failure out of the parser. *)
447
+ match int_of_string_opt (Buffer.contents digits) with
448
+ | None ->
449
+ pos := start;
450
+ None
451
+ | Some min ->
452
+ if !pos < len && pattern.[!pos] = '}' then begin
453
+ incr pos;
454
+ Some (min, Some min)
455
+ end
456
+ else if !pos < len && pattern.[!pos] = ',' then begin
457
+ incr pos;
458
+ let maxdigits = Buffer.create 4 in
459
+ while !pos < len && pattern.[!pos] >= '0' && pattern.[!pos] <= '9' do
460
+ Buffer.add_char maxdigits pattern.[!pos];
461
+ incr pos
462
+ done;
463
+ if !pos < len && pattern.[!pos] = '}' then begin
464
+ incr pos;
465
+ if Buffer.length maxdigits = 0 then Some (min, None)
466
+ else
467
+ match int_of_string_opt (Buffer.contents maxdigits) with
468
+ | Some maxval -> Some (min, Some maxval)
469
+ | None ->
470
+ pos := start;
471
+ None
472
+ end
473
+ else begin
474
+ pos := start;
475
+ None
476
+ end
477
+ end
478
+ else begin
479
+ pos := start;
480
+ None
481
+ end
482
+ end
483
+ in
484
+
485
+ let rec parsealt () =
486
+ let branches = ref [ parseseq () ] in
487
+ while !pos < len && pattern.[!pos] = '|' do
488
+ incr pos;
489
+ branches := !branches @ [ parseseq () ]
490
+ done;
491
+ match !branches with [ single ] -> single | many -> RAlt many
492
+ and parseseq () =
493
+ let nodes = ref [] in
494
+ while !pos < len && pattern.[!pos] <> '|' && pattern.[!pos] <> ')' do
495
+ let atom = parseatom () in
496
+ nodes := !nodes @ [ parserepeat atom ]
497
+ done;
498
+ RSeq !nodes
499
+ and parserepeat atom =
500
+ if !pos >= len then atom
501
+ else
502
+ let bounds =
503
+ match pattern.[!pos] with
504
+ | '*' ->
505
+ incr pos;
506
+ Some (0, None)
507
+ | '+' ->
508
+ incr pos;
509
+ Some (1, None)
510
+ | '?' ->
511
+ incr pos;
512
+ Some (0, Some 1)
513
+ | '{' -> parsecount ()
514
+ | _ -> None
515
+ in
516
+ match bounds with
517
+ | None -> atom
518
+ | Some (min, max) ->
519
+ let greedy = not (!pos < len && pattern.[!pos] = '?') in
520
+ if not greedy then incr pos;
521
+ RRepeat (atom, min, max, greedy)
522
+ and parseatom () =
523
+ let ch = pattern.[!pos] in
524
+ if ch = '(' then begin
525
+ incr pos;
526
+ if !pos + 1 < len && pattern.[!pos] = '?' && pattern.[!pos + 1] = ':' then pos := !pos + 2;
527
+ let inner = parsealt () in
528
+ if !pos >= len || pattern.[!pos] <> ')' then raise (Regex_error "omni: unbalanced regex group");
529
+ incr pos;
530
+ inner
531
+ end
532
+ else if ch = '[' then parseclass ()
533
+ else if ch = '.' then begin
534
+ incr pos;
535
+ RAny
536
+ end
537
+ else if ch = '^' then begin
538
+ incr pos;
539
+ RStart
540
+ end
541
+ else if ch = '$' then begin
542
+ incr pos;
543
+ REnd
544
+ end
545
+ else if ch = '\\' then begin
546
+ incr pos;
547
+ if !pos >= len then raise (Regex_error "omni: trailing backslash in regex");
548
+ let escape = pattern.[!pos] in
549
+ incr pos;
550
+ escapenode escape
551
+ end
552
+ else begin
553
+ incr pos;
554
+ RChar ch
555
+ end
556
+ in
557
+
558
+ let root = parsealt () in
559
+ if !pos < len then raise (Regex_error ("omni: bad regex: " ^ pattern));
560
+ root
561
+
562
+ let isword ch =
563
+ (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch = '_'
564
+
565
+ let isdigitch ch = ch >= '0' && ch <= '9'
566
+ let isspacech ch = ch = ' ' || ch = '\t' || ch = '\n' || ch = '\r' || ch = '\012'
567
+
568
+ let classmatch items negated ch =
569
+ let hit =
570
+ List.exists
571
+ (fun item ->
572
+ match item with
573
+ | IChar want -> ch = want
574
+ | IRange (from, upto) -> from <= ch && ch <= upto
575
+ | IDigit invert -> isdigitch ch <> invert
576
+ | IWord invert -> isword ch <> invert
577
+ | ISpace invert -> isspacech ch <> invert)
578
+ items
579
+ in
580
+ hit <> negated
581
+
582
+ let rec matchnode node text pos cont =
583
+ let len = String.length text in
584
+ match node with
585
+ | RChar want -> pos < len && text.[pos] = want && cont (pos + 1)
586
+ | RAny -> pos < len && cont (pos + 1)
587
+ | RClass (items, negated) -> pos < len && classmatch items negated text.[pos] && cont (pos + 1)
588
+ | RStart -> pos = 0 && cont pos
589
+ | REnd -> pos = len && cont pos
590
+ | RSeq nodes -> matchseq nodes text pos cont
591
+ | RAlt branches -> List.exists (fun branch -> matchnode branch text pos cont) branches
592
+ | RRepeat (inner, min, max, greedy) -> matchrepeat inner min max greedy 0 text pos cont
593
+
594
+ and matchseq nodes text pos cont =
595
+ match nodes with
596
+ | [] -> cont pos
597
+ | head :: rest -> matchnode head text pos (fun next -> matchseq rest text next cont)
598
+
599
+ and matchrepeat inner min max greedy count text pos cont =
600
+ let canmore = match max with None -> true | Some limit -> count < limit in
601
+ let takemore () =
602
+ canmore
603
+ && matchnode inner text pos (fun next ->
604
+ (* A zero-width repeat would loop forever. *)
605
+ next > pos && matchrepeat inner min max greedy (count + 1) text next cont)
606
+ in
607
+ let stopnow () = count >= min && cont pos in
608
+ if greedy then takemore () || stopnow () else stopnow () || takemore ()
609
+
610
+ (* Is the pattern found anywhere in the text? *)
611
+ let regex_find pattern text =
612
+ match regex_parse pattern with
613
+ | exception Regex_error _ -> false
614
+ | root ->
615
+ let len = String.length text in
616
+ let rec attempt start =
617
+ if start > len then false
618
+ else if matchnode root text start (fun _ -> true) then true
619
+ else attempt (start + 1)
620
+ in
621
+ attempt 0
622
+
623
+ (* ---- runner -------------------------------------------------------- *)
624
+
625
+ (* The function under test. Arguments arrive as JSON values; failure is
626
+ reported by raising. *)
627
+ type subject = json list -> json
628
+
629
+ (* A subject that may MUTATE its arguments, which `match.args` can then assert
630
+ on. `minor/setpath` is the case in point: eight of its nine entries assert
631
+ that the store was rewritten in place, and `merge/integrity` all six.
632
+
633
+ OCaml's `json` is immutable, so a consumer holding a converted copy has no
634
+ way to write through a `json list`. The arguments arrive as an ARRAY it may
635
+ overwrite in place, and the runner reads it back after the call.
636
+
637
+ Separate from `subject` rather than replacing it: a signature change would
638
+ break every consumer for a capability most subjects do not need. omni-rust
639
+ and omni-cpp carry the same pair, for the same reason. Dynamic-language
640
+ ports need neither - their shims write the mutation back into omni's own
641
+ object, because the value is shared. *)
642
+ type subject_args = json array -> json
643
+
644
+ (* Run-time options for a set of test entries. *)
645
+ type flags = { null : bool; name : string option }
646
+
647
+ let default_flags = { null = true; name = None }
648
+ let nonull_flags = { null = false; name = None }
649
+
650
+ (* The host of the system under test. Every hook is optional. *)
651
+ type provider = {
652
+ subject : (string -> subject option) option;
653
+ client : (json -> provider) option;
654
+ contextify : (json -> json) option;
655
+ inject : (json -> json -> json) option;
656
+ (* Build the `match.err` base from the failure, REPLACING [errify].
657
+
658
+ OCaml reports a subject failure as its message and nothing else, so a
659
+ library whose errors carry a code has no other way to put one in the
660
+ base. The hook receives that message and returns the base, letting a
661
+ spec assert [match: {err: {code: "x"}}] instead of pattern-matching
662
+ prose. *)
663
+ errify : (string -> json) option;
664
+ }
665
+
666
+ let empty_provider =
667
+ { subject = None; client = None; contextify = None; inject = None; errify = None }
668
+
669
+ (* The newest spec format version this runner understands. A spec with no
670
+ OMNI block is version 0: the original, lenient format, frozen forever.
671
+ Version 1 turns on strict entry validation (see checkentry). *)
672
+ let specversion = 1
673
+
674
+ (* Capability strings this runner supports beyond the version baseline. A
675
+ spec's OMNI.requires list is checked against this: an unknown
676
+ capability refuses the spec loudly at load time, instead of a lagging
677
+ port silently mis-running it. (Empty today; future format features
678
+ mint a string here.) *)
679
+ let capabilities : string list = []
680
+
681
+ (* The complete set of fields an entry may carry. Under version 1 anything
682
+ else is an error: an unrecognised key is almost always a typo'd
683
+ assertion, and a typo'd assertion is a test that silently stopped
684
+ testing. *)
685
+ let entryfields = [ "in"; "args"; "ctx"; "out"; "err"; "match"; "client"; "id"; "doc" ]
686
+
687
+ (* Load a spec: a path to a JSON file. *)
688
+ let loadspec path =
689
+ if not (Sys.file_exists path) then raise (Omni_error ("omni: cannot read spec: " ^ path));
690
+ let channel = open_in_bin path in
691
+ let length = in_channel_length channel in
692
+ let text = really_input_string channel length in
693
+ close_in channel;
694
+ parse text
695
+
696
+ (* Read the spec's format version from its optional top-level OMNI block,
697
+ and refuse a spec this runner cannot faithfully run: a version newer
698
+ than specversion, or a required capability not in capabilities. Only a
699
+ genuinely absent OMNI key is legacy - `OMNI: null` (or a malformed
700
+ requires/version) is a spec error, checked by presence, not by a null
701
+ test, so a present null is never mistaken for absence. *)
702
+ let resolveversion alltests =
703
+ if not (jhas alltests "OMNI") then 0
704
+ else
705
+ let meta = jget alltests "OMNI" in
706
+ if not (ismap meta) then raise (Omni_error "omni: malformed OMNI version block");
707
+
708
+ let version =
709
+ match jget meta "version" with
710
+ | Num v when Float.is_integer v -> v
711
+ | _ -> raise (Omni_error "omni: malformed OMNI version block")
712
+ in
713
+
714
+ if version < 0.0 || float_of_int specversion < version then
715
+ raise (Omni_error ("omni: unsupported spec version: " ^ numstr version));
716
+
717
+ (if jhas meta "requires" then
718
+ match jget meta "requires" with
719
+ | JList items ->
720
+ List.iter
721
+ (fun cap ->
722
+ match cap with
723
+ | Str text when List.mem text capabilities -> ()
724
+ | _ -> raise (Omni_error ("omni: spec requires unsupported capability: " ^ stringify cap)))
725
+ items
726
+ | _ -> raise (Omni_error "omni: malformed OMNI requires list"));
727
+
728
+ int_of_float version
729
+
730
+ (* Find `primary.<name>`, then `<name>`, then the whole spec. *)
731
+ let resolvespec name alltests =
732
+ if name = "" then alltests
733
+ else
734
+ let primary = jget (jget alltests "primary") name in
735
+ if not (isabsent primary) then primary
736
+ else
737
+ let section = jget alltests name in
738
+ if not (isabsent section) then section else alltests
739
+
740
+ (* Nulls (and absent values) become NULLMARK. Always a fresh copy. *)
741
+ let rec fixjson value donull =
742
+ (* Canonical returns the value UNCHANGED when donull is false
743
+ (typescript/src/Runner.ts): absent stays absent and null stays null.
744
+ Answering Null for both collapsed two states the corpus distinguishes, so
745
+ a subject that correctly returned nothing was compared against null and
746
+ marked wrong - `minor/clone#13`, `minor/getprop#4`, `minor/getelem#9`.
747
+ Same defect the other ports carried (#17, #23, #25); this one was missed
748
+ because no consumer had exercised it. *)
749
+ if isnone value then (if donull then Str nullmark else value)
750
+ else
751
+ match value with
752
+ | JList entries -> JList (List.map (fun entry -> fixjson entry donull) entries)
753
+ | JMap entries -> JMap (List.map (fun (key, entry) -> (key, fixjson entry donull)) entries)
754
+ | other -> other
755
+
756
+ (* The JSON form of an error: always at least {name,message}. *)
757
+ let errify message = JMap [ ("name", Str "Error"); ("message", Str message) ]
758
+
759
+ (* The message an `err` expectation matches. *)
760
+ let errmessage err =
761
+ match err with
762
+ | Omni_error message -> message
763
+ | Failure message -> message
764
+ | other -> Printexc.to_string other
765
+
766
+ (* Match one leaf: /regex/ or case-insensitive substring for strings. *)
767
+ let matchval check base =
768
+ if deepequal check base then true
769
+ else
770
+ let want =
771
+ match asstr check with
772
+ | Some text when text = undefmark || text = nullmark -> Null
773
+ | _ -> check
774
+ in
775
+ if isnone want then isnone base || asstr base = Some nullmark
776
+ else
777
+ match asstr want with
778
+ (* An empty want is not a wildcard: the empty string is a substring of
779
+ everything, so `match:{out:""}` (or `err:""`) would accept any value. *)
780
+ | Some "" -> asstr base = Some ""
781
+ | Some text ->
782
+ let basestr = stringify base in
783
+ let tlen = String.length text in
784
+ if tlen > 2 && text.[0] = '/' && text.[tlen - 1] = '/' then
785
+ regex_find (String.sub text 1 (tlen - 2)) basestr
786
+ else
787
+ let lowbase = String.lowercase_ascii basestr in
788
+ let lowwant = String.lowercase_ascii text in
789
+ let blen = String.length lowbase in
790
+ let wlen = String.length lowwant in
791
+ let rec search at =
792
+ if at + wlen > blen then false
793
+ else if String.sub lowbase at wlen = lowwant then true
794
+ else search (at + 1)
795
+ in
796
+ wlen = 0 || search 0
797
+ | None -> deepequal want base
798
+
799
+ (* Convert NULLMARK sentinels back into real nulls. *)
800
+ let nullmodifier value =
801
+ match asstr value with
802
+ | Some text when text = nullmark -> Null
803
+ | Some text ->
804
+ let buf = Buffer.create (String.length text) in
805
+ let mlen = String.length nullmark in
806
+ let at = ref 0 in
807
+ while !at < String.length text do
808
+ if !at + mlen <= String.length text && String.sub text !at mlen = nullmark then begin
809
+ Buffer.add_string buf "null";
810
+ at := !at + mlen
811
+ end
812
+ else begin
813
+ Buffer.add_char buf text.[!at];
814
+ incr at
815
+ end
816
+ done;
817
+ Str (Buffer.contents buf)
818
+ | None -> value
819
+
820
+ (* The spec-defined part of an entry (drop runner bookkeeping). *)
821
+ let entrysummary entry =
822
+ match entry with
823
+ | JMap entries ->
824
+ JMap (List.filter (fun (key, _) -> key <> "res" && key <> "thrown" && key <> "ctx") entries)
825
+ | other -> other
826
+
827
+ (* The label of one entry, for failure messages. *)
828
+ let entryref label index entry =
829
+ let id = jget entry "id" in
830
+ let idpart = if isabsent id then "" else " (" ^ stringify id ^ ")" in
831
+ Printf.sprintf "%s[%d]%s" label index idpart
832
+
833
+ let fail label index entry reason expected actual =
834
+ let buf = Buffer.create 128 in
835
+ Buffer.add_string buf (Printf.sprintf "omni: %s: %s" (entryref label index entry) reason);
836
+ (match expected with
837
+ | Some text -> Buffer.add_string buf ("\n expected: " ^ text)
838
+ | None -> ());
839
+ (match actual with Some text -> Buffer.add_string buf ("\n actual: " ^ text) | None -> ());
840
+ Buffer.add_string buf ("\n entry: " ^ stringify (entrysummary entry));
841
+ Omni_error (Buffer.contents buf)
842
+
843
+ (* Strict entry validation, applied when the spec declares version 1 or
844
+ later. The lenient format converts each of these mistakes into a
845
+ silent pass or a dead field; here they fail with the entry named. *)
846
+ let checkentry label index entry =
847
+ (match entry with
848
+ | JMap fields ->
849
+ List.iter
850
+ (fun (key, _) ->
851
+ if not (List.mem key entryfields) then
852
+ raise (fail label index entry ("unknown entry field: " ^ key) None None))
853
+ fields
854
+ | _ -> raise (fail label index entry "entry is not a map" None None));
855
+
856
+ let argsources = List.length (List.filter (fun key -> jhas entry key) [ "in"; "args"; "ctx" ]) in
857
+ if 1 < argsources then
858
+ raise (fail label index entry "entry has more than one of in, args, ctx" None None);
859
+
860
+ (* `err` here is a presence-and-non-null check (an `err: null` entry is
861
+ not "expects an error"), but `out` is presence alone - the two
862
+ sentinels the rest of the runner distinguishes throughout. *)
863
+ if (not (isnone (jget entry "err"))) && jhas entry "out" then
864
+ raise (fail label index entry "entry has both err and out" None None);
865
+
866
+ if jhas entry "id" && not (isstr (jget entry "id")) then
867
+ raise (fail label index entry "entry id is not a string" None None)
868
+
869
+ (* Validate a version-1 group up front, against the AUTHORED entries -
870
+ null-normalisation would otherwise rewrite an authored null (e.g. id:
871
+ null) into a sentinel string and hide it from validation. A malformed
872
+ spec is a spec error, not a test result, so it fails before any
873
+ subject runs. *)
874
+ let checkset label testspec normalset =
875
+ let origset =
876
+ if ismap testspec then
877
+ match aslist (jget testspec "set") with Some entries -> entries | None -> normalset
878
+ else normalset
879
+ in
880
+
881
+ let emptyflag = match jget testspec "empty" with Bool true -> true | _ -> false in
882
+
883
+ if [] = origset && not emptyflag then raise (Omni_error ("omni: empty test set: " ^ label));
884
+
885
+ List.iteri (fun index entry -> checkentry label index entry) origset
886
+
887
+ (* Check that every leaf of `check` is present, and matches, in `base`. *)
888
+ let rec matchcheck label index entry check base path =
889
+ let where = if path = [] then "<root>" else pathify path in
890
+ match check with
891
+ | JList entries ->
892
+ List.iteri
893
+ (fun at subcheck -> matchcheck label index entry subcheck base (path @ [ string_of_int at ]))
894
+ entries
895
+ | JMap entries ->
896
+ List.iter (fun (key, subcheck) -> matchcheck label index entry subcheck base (path @ [ key ])) entries
897
+ | leaf ->
898
+ let baseval = getpath base path in
899
+ (* The sentinels are tested BEFORE the identity check below. Otherwise a
900
+ subject returning the literal string "__UNDEF__" satisfies an
901
+ assertion that the key is absent - two mutually exclusive states
902
+ passing one check. A sentinel that accepts its own literal is not a
903
+ sentinel. (NULLMARK still accepts NULLMARK: under the default null
904
+ flag a real null has already been normalised to it, so the two are
905
+ genuinely indistinguishable here - that one needs a raw-value escape,
906
+ not an ordering change.) *)
907
+
908
+ (* Explicitly absent: satisfied only by a genuinely missing key, never
909
+ by a present null (the distinction the sentinels exist to keep). *)
910
+ if asstr leaf = Some undefmark then begin
911
+ if not (isabsent baseval) then
912
+ raise
913
+ (fail label index entry ("expected absent at " ^ where) (Some "absent")
914
+ (Some (stringify baseval)))
915
+ end
916
+ (* Explicitly null: satisfied only by a present null. *)
917
+ else if asstr leaf = Some nullmark then begin
918
+ if not (isnull baseval || asstr baseval = Some nullmark) then
919
+ raise
920
+ (fail label index entry ("expected null at " ^ where) (Some "null")
921
+ (Some (stringify baseval)))
922
+ end
923
+ (* Explicitly present: any present value, including null. *)
924
+ else if asstr leaf = Some existsmark then begin
925
+ if isabsent baseval then
926
+ raise
927
+ (fail label index entry ("expected present at " ^ where) (Some "present") (Some "absent"))
928
+ end
929
+ (* Identical values match. This sits below the sentinel branches on
930
+ purpose - see the note above. *)
931
+ else if deepequal leaf baseval then ()
932
+ (* A concrete expectation never matches a missing key - a match leaf
933
+ against an absent value must fail, not substring-match "undefined". *)
934
+ else if isabsent baseval then
935
+ raise
936
+ (fail label index entry ("match failed at " ^ where) (Some (stringify leaf)) (Some "absent"))
937
+ else if not (matchval leaf baseval) then
938
+ raise
939
+ (fail label index entry ("match failed at " ^ where) (Some (stringify leaf))
940
+ (Some (stringify baseval)))
941
+
942
+ let checkresult label index entry args res =
943
+ let entryerr = jget entry "err" in
944
+ if not (isnone entryerr) then
945
+ raise
946
+ (fail label index entry "expected error did not occur" (Some (stringify entryerr))
947
+ (Some (stringify res)));
948
+
949
+ let check = jget entry "match" in
950
+ let matched = not (isnone check) in
951
+
952
+ if matched then begin
953
+ let base =
954
+ JMap
955
+ [
956
+ ("in", jget entry "in");
957
+ ("args", JList args);
958
+ ("out", jget entry "res");
959
+ ("ctx", jget entry "ctx");
960
+ ]
961
+ in
962
+ matchcheck label index entry check base []
963
+ end;
964
+
965
+ let out = jget entry "out" in
966
+
967
+ if deepequal res out then ()
968
+ (* NOTE: a match with no explicit out is a complete check on its own. *)
969
+ else if matched && (isnone out || asstr out = Some nullmark) then ()
970
+ else raise (fail label index entry "result mismatch" (Some (stringify out)) (Some (stringify res)))
971
+
972
+ (* The error base a `match.err` sees: the provider's own, when it has one. *)
973
+ let errbase message (provider : provider) =
974
+ match provider.errify with Some hook -> hook message | None -> errify message
975
+
976
+ let handleerror label index entry message provider =
977
+ let entryerr = jget entry "err" in
978
+
979
+ if isnone entryerr then
980
+ raise (fail label index entry "unexpected error" None (Some message))
981
+ else
982
+ let istrue = match entryerr with Bool true -> true | _ -> false in
983
+ if istrue || matchval entryerr (Str message) then begin
984
+ let check = jget entry "match" in
985
+ if not (isnone check) then
986
+ let base =
987
+ JMap
988
+ [
989
+ ("in", jget entry "in");
990
+ ("out", jget entry "res");
991
+ ("ctx", jget entry "ctx");
992
+ ("err", errbase message provider);
993
+ ]
994
+ in
995
+ matchcheck label index entry check base []
996
+ end
997
+ else
998
+ raise (fail label index entry "error mismatch" (Some (stringify entryerr)) (Some message))
999
+
1000
+ (* What a runner returns for one named spec section. *)
1001
+ type runpack = {
1002
+ spec : json;
1003
+ set : string -> json;
1004
+ runset : json -> subject option -> unit;
1005
+ runsetflags : json -> flags -> subject option -> unit;
1006
+ (* Everything runsetflags does, for a subject that may rewrite its
1007
+ arguments. See `subject_args`. *)
1008
+ runsetflags_args : json -> flags -> subject_args -> unit;
1009
+ defsubject : subject option;
1010
+ client : provider;
1011
+ }
1012
+
1013
+ let resolvesubject name (provider : provider) =
1014
+ if name = "" then None
1015
+ else match provider.subject with None -> None | Some resolve -> resolve name
1016
+
1017
+ (* Make a runner for a spec value and a provider. Resolving the version
1018
+ here - outside the returned closure - fails fast: a spec this runner
1019
+ cannot faithfully run is refused as soon as the runner is made, before
1020
+ any group name is even chosen. *)
1021
+ let make_runner_spec alltests (provider : provider) =
1022
+ let specversion = resolveversion alltests in
1023
+ fun name store ->
1024
+ let spec = resolvespec name alltests in
1025
+
1026
+ (* A spec may define clients that a given test run never references. *)
1027
+ let clients =
1028
+ match (asmap (jget (jget spec "DEF") "client"), provider.client) with
1029
+ | Some entries, Some clientmaker ->
1030
+ List.map
1031
+ (fun (clientname, cdef) ->
1032
+ let copts = jget (jget cdef "test") "options" in
1033
+ let copts = if isabsent copts then JMap [] else copts in
1034
+ let copts =
1035
+ match (provider.inject, store) with
1036
+ | Some inject, Some storeval when ismap storeval -> inject copts storeval
1037
+ | _ -> copts
1038
+ in
1039
+ (clientname, clientmaker copts))
1040
+ entries
1041
+ | _ -> []
1042
+ in
1043
+
1044
+ let defsubject = resolvesubject name provider in
1045
+
1046
+ let drive testspec flags testsubject (argsubject : subject_args option) =
1047
+ let label =
1048
+ match flags.name with Some text -> text | None -> if name = "" then "set" else name
1049
+ in
1050
+
1051
+ let usesubject =
1052
+ match (argsubject, testsubject, defsubject) with
1053
+ | Some _, _, _ -> None
1054
+ | None, Some found, _ -> Some found
1055
+ | None, None, Some found -> Some found
1056
+ | None, None, None -> raise (Omni_error ("omni: no test subject for: " ^ label))
1057
+ in
1058
+
1059
+ let testspecmap = fixjson testspec flags.null in
1060
+ let testset =
1061
+ match aslist (jget testspecmap "set") with
1062
+ | Some entries -> entries
1063
+ | None -> raise (Omni_error ("omni: test spec has no set: " ^ label))
1064
+ in
1065
+
1066
+ (* Validated against the AUTHORED `testspec`, not the null-normalised
1067
+ `testset` above - see checkset. *)
1068
+ if 1 <= specversion then checkset label testspec testset;
1069
+
1070
+ List.iteri
1071
+ (fun index rawentry ->
1072
+ if not (ismap rawentry) then
1073
+ raise (Omni_error (Printf.sprintf "omni: %s[%d]: entry is not a map" label index));
1074
+
1075
+ (* An entry with no `out` expects a null (or absent) result. *)
1076
+ let entry =
1077
+ if flags.null && isnone (jget rawentry "out") then jset rawentry "out" (Str nullmark)
1078
+ else rawentry
1079
+ in
1080
+
1081
+ let entrysubject =
1082
+ match (usesubject, asstr (jget entry "client")) with
1083
+ | None, _ -> None
1084
+ | Some found, None -> Some found
1085
+ | Some found, Some clientname -> (
1086
+ match List.assoc_opt clientname clients with
1087
+ | None -> raise (Omni_error ("omni: unknown client: " ^ clientname))
1088
+ | Some client -> (
1089
+ match resolvesubject name client with Some other -> Some other | None -> Some found))
1090
+ in
1091
+
1092
+ (* Build the argument list: `ctx`, `args`, or `in`. *)
1093
+ let hasctx = jhas entry "ctx" in
1094
+ let hasargs = jhas entry "args" in
1095
+ let args =
1096
+ if hasctx then [ jget entry "ctx" ]
1097
+ else if hasargs then
1098
+ match aslist (jget entry "args") with Some list -> list | None -> [ jget entry "args" ]
1099
+ else [ clone (jget entry "in") ]
1100
+ in
1101
+
1102
+ let args, entry =
1103
+ if (hasctx || hasargs) && args <> [] && ismap (List.hd args) then
1104
+ let first =
1105
+ match provider.contextify with
1106
+ | Some contextify -> contextify (List.hd args)
1107
+ | None -> List.hd args
1108
+ in
1109
+ (* The resolved client is a live provider (closures over the
1110
+ system under test), and this port's json carries no
1111
+ host-object variant to hold one - so canonical's
1112
+ `first.client = testpack.client` becomes presence, not
1113
+ identity: enough for a subject to prove the runner
1114
+ attached a client at all. *)
1115
+ let first = jset first "client" (Bool true) in
1116
+ (first :: List.tl args, jset entry "ctx" first)
1117
+ else (args, entry)
1118
+ in
1119
+
1120
+ (* An args-subject may overwrite its argument array; the runner reads
1121
+ it back so `match.args` sees what the subject actually did. *)
1122
+ let invoke () =
1123
+ match (argsubject, entrysubject) with
1124
+ | Some call, _ ->
1125
+ let cells = Array.of_list args in
1126
+ let res = call cells in
1127
+ (Array.to_list cells, res)
1128
+ | None, Some call -> (args, call args)
1129
+ | None, None -> raise (Omni_error ("omni: no test subject for: " ^ label))
1130
+ in
1131
+
1132
+ match invoke () with
1133
+ | args, res ->
1134
+ let fixed = fixjson res flags.null in
1135
+ checkresult label index (jset entry "res" fixed) args fixed
1136
+ | exception Omni_error message -> raise (Omni_error message)
1137
+ | exception err -> handleerror label index entry (errmessage err) provider)
1138
+ testset
1139
+ in
1140
+
1141
+ let runsetflags testspec flags testsubject = drive testspec flags testsubject None in
1142
+ let runsetflags_args testspec flags argsubject =
1143
+ drive testspec flags None (Some argsubject)
1144
+ in
1145
+
1146
+ {
1147
+ spec;
1148
+ set = (fun setname -> jget spec setname);
1149
+ runset = (fun testspec testsubject -> runsetflags testspec default_flags testsubject);
1150
+ runsetflags;
1151
+ runsetflags_args;
1152
+ defsubject;
1153
+ client = provider;
1154
+ }
1155
+
1156
+ (* Make a runner for a spec file path and a provider. *)
1157
+ let make_runner path (provider : provider) = make_runner_spec (loadspec path) provider