@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.
- package/bin/voxgig-sdkgen +1 -1
- package/dist/action/doctor.d.ts +1 -0
- package/dist/action/doctor.js +50 -2
- package/dist/action/doctor.js.map +1 -1
- package/dist/helpers/naming.js +4 -2
- package/dist/helpers/naming.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/model/sdkgen.aon +21 -0
- package/package.json +1 -1
- package/project/.sdk/model/feature/secrets.aon +120 -18
- package/project/.sdk/model/target/c.aon +10 -0
- package/project/.sdk/model/target/clojure.aon +13 -0
- package/project/.sdk/model/target/cpp.aon +10 -0
- package/project/.sdk/model/target/csharp.aon +9 -0
- package/project/.sdk/model/target/dart.aon +10 -0
- package/project/.sdk/model/target/elixir.aon +9 -0
- package/project/.sdk/model/target/go.aon +13 -0
- package/project/.sdk/model/target/java.aon +9 -0
- package/project/.sdk/model/target/js.aon +7 -0
- package/project/.sdk/model/target/kotlin.aon +9 -0
- package/project/.sdk/model/target/lean.aon +17 -0
- package/project/.sdk/model/target/lua.aon +8 -0
- package/project/.sdk/model/target/ocaml.aon +9 -0
- package/project/.sdk/model/target/perl.aon +8 -0
- package/project/.sdk/model/target/php.aon +8 -0
- package/project/.sdk/model/target/py.aon +13 -0
- package/project/.sdk/model/target/rb.aon +8 -0
- package/project/.sdk/model/target/rust.aon +10 -0
- package/project/.sdk/model/target/scala.aon +21 -2
- package/project/.sdk/model/target/swift.aon +18 -0
- package/project/.sdk/model/target/ts.aon +13 -0
- package/project/.sdk/model/target/zig.aon +9 -0
- package/project/.sdk/src/cmp/clojure/Package_clojure.ts +9 -2
- package/project/.sdk/src/cmp/cpp/Gitignore_cpp.ts +3 -0
- package/project/.sdk/src/cmp/dart/Test_dart.ts +2 -0
- package/project/.sdk/src/cmp/elixir/Package_elixir.ts +4 -1
- package/project/.sdk/src/cmp/go/Config_go.ts +59 -2
- package/project/.sdk/src/cmp/go/Main_go.ts +8 -2
- package/project/.sdk/src/cmp/java/Test_java.ts +6 -5
- package/project/.sdk/src/cmp/kotlin/Test_kotlin.ts +6 -5
- package/project/.sdk/src/cmp/lean/Package_lean.ts +23 -0
- package/project/.sdk/src/cmp/lean/ReadmeInstall_lean.ts +1 -0
- package/project/.sdk/src/cmp/lean/ReadmeTopTest_lean.ts +1 -0
- package/project/.sdk/src/cmp/ocaml/Gitignore_ocaml.ts +1 -0
- package/project/.sdk/src/cmp/ocaml/Main_ocaml.ts +7 -3
- package/project/.sdk/src/cmp/py/Config_py.ts +82 -1
- package/project/.sdk/src/cmp/py/Main_py.ts +44 -0
- package/project/.sdk/src/cmp/py/fragment/Main.fragment.py +2 -0
- package/project/.sdk/src/cmp/swift/Main_swift.ts +10 -0
- package/project/.sdk/src/cmp/swift/Package_swift.ts +13 -1
- package/project/.sdk/src/cmp/ts/Config_ts.ts +42 -17
- package/project/.sdk/src/cmp/ts/fragment/Config.data.fragment.ts +13 -1
- package/project/.sdk/src/cmp/ts/fragment/Config.fragment.ts +13 -1
- package/project/.sdk/src/cmp/zig/Package_zig.ts +15 -11
- package/project/.sdk/src/cmp/zig/fragment/Entity.fragment.zig +3 -3
- package/project/.sdk/src/cmp/zig/fragment/EntityListOp.fragment.zig +3 -3
- package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +3 -3
- package/project/.sdk/src/cmp/zig/utility_zig.ts +50 -1
- package/project/.sdk/tm/c/Makefile +38 -3
- package/project/.sdk/tm/c/tests/omni_resolver.h +361 -0
- package/project/.sdk/tm/c/tests/omni_smoke_test.c +237 -0
- package/project/.sdk/tm/c/tests/primary_corpus_test.c +205 -284
- package/project/.sdk/tm/c/tests/struct_corpus_test.c +292 -212
- package/project/.sdk/tm/c/tests/vendor/omni/json.c +811 -0
- package/project/.sdk/tm/c/tests/vendor/omni/omni.h +240 -0
- package/project/.sdk/tm/c/tests/vendor/omni/runner.c +940 -0
- package/project/.sdk/tm/c/tests/vendor/omni/util.c +351 -0
- package/project/.sdk/tm/c/utility/struct/utility.c +7 -2
- package/project/.sdk/tm/clojure/test/sdk/test/omni.clj +401 -0
- package/project/.sdk/tm/clojure/test/sdk/test/omni_smoke.clj +81 -0
- package/project/.sdk/tm/clojure/test/sdk/test/primary.clj +92 -58
- package/project/.sdk/tm/clojure/test/sdk/test/struct_corpus.clj +122 -149
- package/project/.sdk/tm/clojure/test/sdk/test_runner.clj +8 -3
- package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/json.clj +145 -0
- package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/runner.clj +445 -0
- package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/util.clj +145 -0
- package/project/.sdk/tm/cpp/Makefile +5 -1
- package/project/.sdk/tm/cpp/test/omni_resolver.hpp +473 -0
- package/project/.sdk/tm/cpp/test/omni_smoke_test.cpp +209 -0
- package/project/.sdk/tm/cpp/test/primary_utility_test.cpp +243 -184
- package/project/.sdk/tm/cpp/test/runner_support.hpp +68 -181
- package/project/.sdk/tm/cpp/test/struct_corpus_test.cpp +183 -56
- package/project/.sdk/tm/cpp/test/vendor/omni/json.hpp +406 -0
- package/project/.sdk/tm/cpp/test/vendor/omni/omni.hpp +751 -0
- package/project/.sdk/tm/cpp/test/vendor/omni/util.hpp +256 -0
- package/project/.sdk/tm/cpp/utility/pipeline.hpp +7 -1
- package/project/.sdk/tm/csharp/test/OmniResolver.cs +491 -0
- package/project/.sdk/tm/csharp/test/OmniSmokeTest.cs +106 -0
- package/project/.sdk/tm/csharp/test/PrimaryUtilityTest.cs +299 -316
- package/project/.sdk/tm/csharp/test/Runner.cs +104 -269
- package/project/.sdk/tm/csharp/test/StructUtilityTest.cs +535 -724
- package/project/.sdk/tm/csharp/test/vendor/omni/Runner.cs +864 -0
- package/project/.sdk/tm/csharp/test/vendor/omni/Util.cs +347 -0
- package/project/.sdk/tm/csharp/utility/MakeSpec.cs +3 -1
- package/project/.sdk/tm/csharp/utility/PrepareMethod.cs +6 -1
- package/project/.sdk/tm/csharp/utility/struct/Struct.cs +21 -5
- package/project/.sdk/tm/dart/test/omni.dart +520 -0
- package/project/.sdk/tm/dart/test/omni_smoke_test.dart +143 -0
- package/project/.sdk/tm/dart/test/primary_test.dart +86 -28
- package/project/.sdk/tm/dart/test/struct_test.dart +438 -11
- package/project/.sdk/tm/dart/test/vendor/omni/omni.dart +7 -0
- package/project/.sdk/tm/dart/test/vendor/omni/runner.dart +653 -0
- package/project/.sdk/tm/dart/test/vendor/omni/util.dart +232 -0
- package/project/.sdk/tm/elixir/Makefile +11 -3
- package/project/.sdk/tm/elixir/test/omni_smoke_test.exs +117 -0
- package/project/.sdk/tm/elixir/test/primary_utility_test.exs +341 -16
- package/project/.sdk/tm/elixir/test/struct_corpus_test.exs +554 -9
- package/project/.sdk/tm/elixir/test/support/omni.ex +377 -0
- package/project/.sdk/tm/elixir/test/vendor/omni/json.ex +122 -0
- package/project/.sdk/tm/elixir/test/vendor/omni/runner.ex +623 -0
- package/project/.sdk/tm/elixir/test/vendor/omni/util.ex +187 -0
- package/project/.sdk/tm/go/core/context.go +32 -16
- package/project/.sdk/tm/go/feature/secrets/plugin/capability.go +261 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/catalog.go +78 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/config.go +652 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/depend.go +250 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/env.go +194 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/export.go +80 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/graph.go +238 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/host.go +1575 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/order.go +248 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/point.go +184 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/ref.go +123 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/resolve.go +79 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/types.go +296 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/util.go +87 -0
- package/project/.sdk/tm/go/feature/secrets/plugin/version.go +161 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/aws/aws.go +292 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/aws/sigv4.go +201 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/azuresecrets/azuresecrets.go +187 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/boru/boru.go +184 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/doppler/doppler.go +114 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/gcpsecrets/gcpsecrets.go +156 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/hashicorp/hashicorp.go +208 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/httpjson/httpjson.go +241 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/infisical/infisical.go +150 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/onepassword/onepassword.go +152 -0
- package/project/.sdk/tm/go/feature/secrets/plugins/secretspec/secretspec.go +143 -0
- package/project/.sdk/tm/go/feature/secrets/sekreto/addr.go +120 -0
- package/project/.sdk/tm/go/feature/secrets/sekreto/providers.go +442 -0
- package/project/.sdk/tm/go/feature/secrets/sekreto/sekreto.go +714 -0
- package/project/.sdk/tm/go/feature/secrets_feature.go +675 -0
- package/project/.sdk/tm/go/src/feature/secrets/.gitkeep +0 -0
- package/project/.sdk/tm/go/test/feature/secrets/secrets_feature_test.go +799 -0
- package/project/.sdk/tm/go/test/omni/omni.go +902 -0
- package/project/.sdk/tm/go/test/omni/util.go +381 -0
- package/project/.sdk/tm/go/test/omniresolver_test.go +748 -0
- package/project/.sdk/tm/go/test/omnismoke_test.go +112 -0
- package/project/.sdk/tm/go/test/primary_utility_test.go +123 -191
- package/project/.sdk/tm/go/test/struct_utility_test.go +323 -16
- package/project/.sdk/tm/go/test/testsupport_test.go +294 -0
- package/project/.sdk/tm/go/utility/make_options.go +8 -1
- package/project/.sdk/tm/go/utility/prepare_method.go +5 -1
- package/project/.sdk/tm/go/utility/struct/voxgigstruct.go +2 -2
- package/project/.sdk/tm/java/test/OmniResolver.java +355 -0
- package/project/.sdk/tm/java/test/OmniSmokeTest.java +99 -0
- package/project/.sdk/tm/java/test/PrimaryUtilityTest.java +254 -280
- package/project/.sdk/tm/java/test/RunnerSupport.java +9 -194
- package/project/.sdk/tm/java/test/StructCorpusTest.java +119 -42
- package/project/.sdk/tm/java/test/vendor/omni/Json.java +287 -0
- package/project/.sdk/tm/java/test/vendor/omni/Runner.java +851 -0
- package/project/.sdk/tm/java/test/vendor/omni/Util.java +322 -0
- package/project/.sdk/tm/java/utility/MakeSpec.java +3 -1
- package/project/.sdk/tm/java/utility/PrepareMethod.java +5 -5
- package/project/.sdk/tm/java/utility/struct/Struct.java +17 -4
- package/project/.sdk/tm/js/src/utility/StructUtility.js +3 -3
- package/project/.sdk/tm/js/test/omni.js +251 -0
- package/project/.sdk/tm/js/test/omni.test.js +105 -0
- package/project/.sdk/tm/js/test/utility/PrimaryUtility.test.js +6 -2
- package/project/.sdk/tm/js/test/utility/StructUtility.test.js +27 -2
- package/project/.sdk/tm/js/test/vendor/omni/index.js +77 -0
- package/project/.sdk/tm/js/test/vendor/omni/runner.js +628 -0
- package/project/.sdk/tm/js/test/vendor/omni/util.js +229 -0
- package/project/.sdk/tm/kotlin/core/Utility.kt +1 -1
- package/project/.sdk/tm/kotlin/test/OmniResolver.kt +343 -0
- package/project/.sdk/tm/kotlin/test/OmniSmokeTest.kt +100 -0
- package/project/.sdk/tm/kotlin/test/PrimaryUtilityTest.kt +244 -262
- package/project/.sdk/tm/kotlin/test/RunnerSupport.kt +9 -178
- package/project/.sdk/tm/kotlin/test/StructCorpusTest.kt +121 -32
- package/project/.sdk/tm/kotlin/test/vendor/omni/Json.kt +264 -0
- package/project/.sdk/tm/kotlin/test/vendor/omni/Runner.kt +615 -0
- package/project/.sdk/tm/kotlin/test/vendor/omni/Util.kt +139 -0
- package/project/.sdk/tm/kotlin/utility/MakeSpecUrl.kt +6 -3
- package/project/.sdk/tm/kotlin/utility/Prepare.kt +6 -6
- package/project/.sdk/tm/kotlin/utility/struct/Struct.kt +18 -2
- package/project/.sdk/tm/lean/Makefile +12 -5
- package/project/.sdk/tm/lean/src/SdkUtility.lean +14 -1
- package/project/.sdk/tm/lean/test/OmniResolver.lean +358 -0
- package/project/.sdk/tm/lean/test/OmniSmoke.lean +174 -0
- package/project/.sdk/tm/lean/test/StructCorpus.lean +245 -574
- package/project/.sdk/tm/lean/test/TPrimaryUtility.lean +155 -291
- package/project/.sdk/tm/lean/test/vendor/omni/Omni.lean +997 -0
- package/project/.sdk/tm/lua/test/omni.lua +456 -0
- package/project/.sdk/tm/lua/test/omni_smoke_test.lua +103 -0
- package/project/.sdk/tm/lua/test/primary_utility_test.lua +250 -509
- package/project/.sdk/tm/lua/test/struct_utility_test.lua +161 -70
- package/project/.sdk/tm/lua/test/vendor/omni/json.lua +268 -0
- package/project/.sdk/tm/lua/test/vendor/omni/regex.lua +385 -0
- package/project/.sdk/tm/lua/test/vendor/omni/runner.lua +641 -0
- package/project/.sdk/tm/lua/test/vendor/omni/util.lua +282 -0
- package/project/.sdk/tm/lua/utility/prepare_method.lua +5 -1
- package/project/.sdk/tm/lua/utility/struct/regex.lua +663 -0
- package/project/.sdk/tm/lua/utility/struct/struct.lua +660 -420
- package/project/.sdk/tm/ocaml/Makefile +37 -12
- package/project/.sdk/tm/ocaml/test/omni_resolver.ml +284 -0
- package/project/.sdk/tm/ocaml/test/omni_smoke_test.ml +169 -0
- package/project/.sdk/tm/ocaml/test/primary_utility_test.ml +84 -100
- package/project/.sdk/tm/ocaml/test/struct_corpus.ml +225 -201
- package/project/.sdk/tm/ocaml/test/vendor/omni/omni.ml +1157 -0
- package/project/.sdk/tm/perl/lib/Voxgig/Struct.pm +88 -12
- package/project/.sdk/tm/perl/t/omni.pm +647 -0
- package/project/.sdk/tm/perl/t/omni_smoke.t +87 -0
- package/project/.sdk/tm/perl/t/primary_utility.t +189 -487
- package/project/.sdk/tm/perl/t/struct_utility.t +455 -389
- package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni/Runner.pm +649 -0
- package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni/Util.pm +253 -0
- package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni.pm +24 -0
- package/project/.sdk/tm/perl/utility/prepare_method.pm +7 -2
- package/project/.sdk/tm/php/test/Omni.php +691 -0
- package/project/.sdk/tm/php/test/OmniSmokeTest.php +93 -0
- package/project/.sdk/tm/php/test/PrimaryUtilityTest.php +210 -571
- package/project/.sdk/tm/php/test/StructUtilityTest.php +320 -342
- package/project/.sdk/tm/php/test/vendor/omni/Runner.php +644 -0
- package/project/.sdk/tm/php/test/vendor/omni/Util.php +283 -0
- package/project/.sdk/tm/php/utility/MakeSpec.php +10 -3
- package/project/.sdk/tm/php/utility/PrepareBody.php +7 -1
- package/project/.sdk/tm/php/utility/PrepareMethod.php +6 -2
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/__init__.py +36 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/capability.py +141 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/catalog.py +50 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/config.py +333 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/depend.py +198 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/env.py +147 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/export.py +52 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/graph.py +139 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/host.py +1053 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/order.py +171 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/point.py +95 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/ref.py +116 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/resolve.py +59 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/types.py +87 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/version.py +112 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/__init__.py +76 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/addr.py +116 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/aws.py +192 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/azuresecrets.py +120 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/boru.py +140 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/doppler.py +62 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/gcpsecrets.py +101 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/hashicorp.py +151 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/httpjson.py +115 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/infisical.py +90 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/onepassword.py +101 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/secretspec.py +119 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/sigv4.py +125 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/providers.py +211 -0
- package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/sekreto.py +475 -0
- package/project/.sdk/tm/py/pkg/feature/secrets_feature.py +467 -0
- package/project/.sdk/tm/py/pkg/utility/prepare_method.py +5 -1
- package/project/.sdk/tm/py/pkg/utility/voxgig_struct/__init__.py +0 -2
- package/project/.sdk/tm/py/pkg/utility/voxgig_struct/voxgig_struct.py +780 -529
- package/project/.sdk/tm/py/src/feature/secrets/.gitkeep +0 -0
- package/project/.sdk/tm/py/test/feature/__init__.py +0 -0
- package/project/.sdk/tm/py/test/feature/secrets/__init__.py +0 -0
- package/project/.sdk/tm/py/test/feature/secrets/test_secrets.py +337 -0
- package/project/.sdk/tm/py/test/omni.py +415 -0
- package/project/.sdk/tm/py/test/test_omni_smoke.py +74 -0
- package/project/.sdk/tm/py/test/test_primary_utility.py +144 -668
- package/project/.sdk/tm/py/test/test_struct_utility.py +74 -27
- package/project/.sdk/tm/py/test/voxgig_omni/__init__.py +62 -0
- package/project/.sdk/tm/py/test/voxgig_omni/runner.py +580 -0
- package/project/.sdk/tm/py/test/voxgig_omni/util.py +252 -0
- package/project/.sdk/tm/rb/test/omni.rb +505 -0
- package/project/.sdk/tm/rb/test/omni_smoke_test.rb +72 -0
- package/project/.sdk/tm/rb/test/primary_utility_test.rb +174 -560
- package/project/.sdk/tm/rb/test/struct_utility_test.rb +13 -7
- package/project/.sdk/tm/rb/test/vendor/omni/runner.rb +493 -0
- package/project/.sdk/tm/rb/test/vendor/omni/util.rb +199 -0
- package/project/.sdk/tm/rb/test/vendor/omni/voxgig_omni.rb +15 -0
- package/project/.sdk/tm/rb/utility/prepare_method.rb +5 -1
- package/project/.sdk/tm/rust/tests/common/mod.rs +19 -242
- package/project/.sdk/tm/rust/tests/omni_resolver/mod.rs +888 -0
- package/project/.sdk/tm/rust/tests/omni_smoke_test.rs +286 -0
- package/project/.sdk/tm/rust/tests/primary_utility_test.rs +318 -312
- package/project/.sdk/tm/rust/tests/struct_utility_test.rs +66 -28
- package/project/.sdk/tm/rust/tests/vendor/omni/json.rs +412 -0
- package/project/.sdk/tm/rust/tests/vendor/omni/mod.rs +38 -0
- package/project/.sdk/tm/rust/tests/vendor/omni/regex.rs +392 -0
- package/project/.sdk/tm/rust/tests/vendor/omni/runner.rs +1001 -0
- package/project/.sdk/tm/rust/tests/vendor/omni/util.rs +161 -0
- package/project/.sdk/tm/rust/utility/prepare_method.rs +5 -1
- package/project/.sdk/tm/scala/Makefile +16 -6
- package/project/.sdk/tm/scala/sdktest/OmniResolver.scala +497 -0
- package/project/.sdk/tm/scala/sdktest/OmniSmoke.scala +192 -0
- package/project/.sdk/tm/scala/sdktest/PrimaryCorpus.scala +47 -19
- package/project/.sdk/tm/scala/sdktest/StructCorpus.scala +0 -0
- package/project/.sdk/tm/scala/sdktest/vendor/omni/Json.scala +229 -0
- package/project/.sdk/tm/scala/sdktest/vendor/omni/Runner.scala +552 -0
- package/project/.sdk/tm/scala/sdktest/vendor/omni/Util.scala +104 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Constants.swift +10 -0
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Inject.swift +28 -5
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Injection.swift +5 -1
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Minor.swift +4 -1
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/Struct/Validate.swift +15 -5
- package/project/.sdk/tm/swift/Sources/ProjectNameSDK/utility/Prepare.swift +6 -1
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/OmniResolver.swift +474 -0
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/OmniSmokeTest.swift +107 -0
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/PrimaryUtilityTest.swift +141 -178
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/Runner.swift +17 -113
- package/project/.sdk/tm/swift/Tests/ProjectNameSDKTests/StructUtilityTest.swift +295 -446
- package/project/.sdk/tm/swift/Tests/vendor/omni/Json.swift +364 -0
- package/project/.sdk/tm/swift/Tests/vendor/omni/Runner.swift +730 -0
- package/project/.sdk/tm/swift/Tests/vendor/omni/Util.swift +162 -0
- package/project/.sdk/tm/ts/src/feature/secrets/SecretsFeature.ts +7 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Capability.ts +148 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Catalog.ts +55 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Config.ts +344 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Depend.ts +205 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Env.ts +138 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Export.ts +46 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/FeatureHost.ts +349 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Graph.ts +181 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Host.ts +1132 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Order.ts +177 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Point.ts +119 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Ref.ts +102 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Resolve.ts +61 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Types.ts +112 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/Version.ts +100 -0
- package/project/.sdk/tm/ts/src/feature/secrets/plugin/index.ts +37 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sekreto.ts +163 -30
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/index.ts +27 -22
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/aws.ts +26 -36
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/azuresecrets.ts +19 -21
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/boru.ts +36 -17
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/doppler.ts +14 -21
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/gcpsecrets.ts +27 -27
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/hashicorp.ts +25 -39
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/httpjson.ts +99 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/infisical.ts +14 -16
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{provider → plugins}/onepassword.ts +15 -22
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/secretspec.ts +98 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/{Sigv4.ts → plugins/sigv4.ts} +7 -6
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/addr.ts +97 -23
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/builtin.ts +37 -0
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/dotenv.ts +4 -17
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/env.ts +4 -16
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/file.ts +11 -25
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/memory.ts +6 -23
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/support.ts +106 -39
- package/project/.sdk/tm/ts/src/utility/StructUtility.ts +3 -3
- package/project/.sdk/tm/ts/test/omni.ts +104 -32
- package/project/.sdk/tm/ts/test/utility/StructUtility.test.ts +27 -0
- package/project/.sdk/tm/ts/test/vendor/omni/Runner.ts +32 -5
- package/project/.sdk/tm/ts/test/vendor/omni/Util.ts +2 -2
- package/project/.sdk/tm/ts/test/vendor/omni/index.ts +2 -2
- package/project/.sdk/tm/zig/Makefile +15 -1
- package/project/.sdk/tm/zig/build.zig +23 -5
- package/project/.sdk/tm/zig/core/helpers.zig +52 -11
- package/project/.sdk/tm/zig/core/mem.zig +17 -1
- package/project/.sdk/tm/zig/core/utility.zig +23 -19
- package/project/.sdk/tm/zig/feature/audit.zig +2 -2
- package/project/.sdk/tm/zig/feature/cache.zig +2 -2
- package/project/.sdk/tm/zig/feature/debug.zig +5 -5
- package/project/.sdk/tm/zig/feature/netsim.zig +2 -2
- package/project/.sdk/tm/zig/feature/paging.zig +2 -2
- package/project/.sdk/tm/zig/feature/proxy.zig +15 -8
- package/project/.sdk/tm/zig/feature/streaming.zig +5 -5
- package/project/.sdk/tm/zig/feature/support.zig +3 -3
- package/project/.sdk/tm/zig/feature/telemetry.zig +5 -5
- package/project/.sdk/tm/zig/feature/test.zig +10 -5
- package/project/.sdk/tm/zig/test/fh.zig +10 -10
- package/project/.sdk/tm/zig/test/gotcha_test.zig +5 -5
- package/project/.sdk/tm/zig/test/omniresolver.zig +515 -0
- package/project/.sdk/tm/zig/test/omnismoke_test.zig +284 -0
- package/project/.sdk/tm/zig/test/pipeline_test.zig +8 -8
- package/project/.sdk/tm/zig/test/primary_utility_test.zig +145 -155
- package/project/.sdk/tm/zig/test/struct_corpus.zig +264 -187
- package/project/.sdk/tm/zig/test/vendor/omni/omni.zig +1314 -0
- package/project/.sdk/tm/zig/test/vendor/omni/regex.zig +446 -0
- package/project/.sdk/tm/zig/utility/voxgigstruct/regex.zig +7 -4
- package/project/.sdk/tm/zig/utility/voxgigstruct/struct.zig +356 -157
- package/project/sdkgen-package.json +1 -1
- package/src/action/doctor.ts +66 -2
- package/src/helpers/naming.ts +4 -2
- package/project/.sdk/tm/c/tests/runner.h +0 -274
- package/project/.sdk/tm/cpp/test/struct_runner.hpp +0 -314
- package/project/.sdk/tm/csharp/test/StructRunner.cs +0 -276
- package/project/.sdk/tm/dart/test/runner.dart +0 -406
- package/project/.sdk/tm/dart/test/struct_corpus.dart +0 -531
- package/project/.sdk/tm/elixir/test/support/struct_corpus.ex +0 -1088
- package/project/.sdk/tm/go/test/runner_test.go +0 -629
- package/project/.sdk/tm/go/test/struct_runner_test.go +0 -1094
- package/project/.sdk/tm/java/test/StructRunner.java +0 -281
- package/project/.sdk/tm/js/test/runner.js +0 -387
- package/project/.sdk/tm/kotlin/test/StructRunner.kt +0 -177
- package/project/.sdk/tm/lua/test/struct_runner.lua +0 -602
- package/project/.sdk/tm/ocaml/test/corpus_runner.ml +0 -185
- package/project/.sdk/tm/perl/t/struct_runner.pm +0 -275
- package/project/.sdk/tm/php/test/StructRunner.php +0 -275
- package/project/.sdk/tm/py/test/struct_runner.py +0 -411
- package/project/.sdk/tm/rb/test/struct_runner.rb +0 -309
- package/project/.sdk/tm/rust/tests/struct_runner/mod.rs +0 -424
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/Registry.ts +0 -90
- package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/http.ts +0 -66
- package/project/.sdk/tm/ts/test/vendor/omni/compat.ts +0 -188
- package/project/.sdk/tm/zig/test/struct_runner.zig +0 -464
|
@@ -0,0 +1,888 @@
|
|
|
1
|
+
// The corpus test runner: vendored @voxgig/omni driven through its NATIVE
|
|
2
|
+
// API (`omni::runner::make_runner` / `RunPack::runsetflags_args`), presented
|
|
3
|
+
// to the corpus suites in the struct-runner shape they already use
|
|
4
|
+
// (`run.spec`, `run.set`, `run.run_set`, `run.run_set_fallible`,
|
|
5
|
+
// `run.passed`, `run.failures`). No compat shim is vendored: the adapter
|
|
6
|
+
// below IS the whole bridge, per language, per the vendor-tag rollout
|
|
7
|
+
// (docs/design/vendor-tag-rollout.md, Decision 4). It supersedes the whole
|
|
8
|
+
// of the retired `tests/struct_runner/mod.rs` and the corpus ENGINE half of
|
|
9
|
+
// `tests/common/mod.rs` (`runset`/`runset_named`/`match_deep`/`match_string`
|
|
10
|
+
// went with it; that file's SUPPORT half — env, sdk-test-control, ctx
|
|
11
|
+
// construction, the fh harness — is retained under its own name, so the
|
|
12
|
+
// emitted call sites did not move).
|
|
13
|
+
//
|
|
14
|
+
// It is the Rust peer of tm/csharp/test/OmniResolver.cs,
|
|
15
|
+
// tm/java/test/OmniResolver.java and
|
|
16
|
+
// tm/swift/Tests/ProjectNameSDKTests/OmniResolver.swift, and it follows the
|
|
17
|
+
// bridge voxgig/struct's own rust corpus harness already uses
|
|
18
|
+
// (struct/rust/corpus/tests/omni.rs) — the portable answer for a statically
|
|
19
|
+
// typed port with no reflection: omni's `Provider` is closure-based, so
|
|
20
|
+
// nothing in omni ever has to name this SDK's types.
|
|
21
|
+
//
|
|
22
|
+
// Rust-specific decisions, each load-bearing:
|
|
23
|
+
//
|
|
24
|
+
// 1. TWO VALUE MODELS, ONE CONVERSION PAIR. omni's `Json` and the SDK's
|
|
25
|
+
// `voxgigstruct::Value` are different enums, so every crossing is an
|
|
26
|
+
// explicit `tostruct` / `toomni`. `Json::Absent` <-> `Value::Noval` and
|
|
27
|
+
// `Json::Null` <-> `Value::Null` keep the two no-value states the corpus
|
|
28
|
+
// distinguishes apart — which is also why Rust needs neither go's
|
|
29
|
+
// `novalargs` spec rewrite nor lua/php's compat shim for the corpus's
|
|
30
|
+
// zero-argument entries (an entry with no `in`/`args`/`ctx` arrives as
|
|
31
|
+
// one `Json::Absent`, and becomes exactly this port's own NOVAL).
|
|
32
|
+
//
|
|
33
|
+
// 2. ARGUMENTS ARE WRITTEN BACK. `SubjectArgs` (`Fn(&mut [Json])`) is the
|
|
34
|
+
// channel omni provides for a subject that MUTATES its arguments, which
|
|
35
|
+
// `match: {args: ...}` then asserts on — `struct/minor/setpath` and
|
|
36
|
+
// `struct/merge/integrity` turn on it. Decision 1 handed the subject a
|
|
37
|
+
// CONVERTED COPY, so every subject here runs through `runsetflags_args`
|
|
38
|
+
// and the wrapper converts the (possibly mutated) `Value` arguments back
|
|
39
|
+
// into omni's own slice after the call. A dynamic port's shim gets this
|
|
40
|
+
// for free from shared object identity; Rust cannot.
|
|
41
|
+
//
|
|
42
|
+
// 3. `match: {ctx: ...}` IS RETARGETED ONTO `match: {args: {"0": ...}}`.
|
|
43
|
+
// The one place this port cannot follow canonical omni as written, and a
|
|
44
|
+
// VALUE-SEMANTICS consequence, not a choice. omni's `Json` is a plain
|
|
45
|
+
// enum: `resolveargs` stores `entry.ctx` and `args[0]` as two COPIES of
|
|
46
|
+
// the contextified map, and `checkresult` reads `entry.get("ctx")` for
|
|
47
|
+
// the ctx base — so a subject's post-call writes (decision 2) can never
|
|
48
|
+
// reach the copy `entry.ctx` holds, and nine `primary` entries assert
|
|
49
|
+
// exactly that post-call state. args[0] IS the ctx of a ctx entry (omni
|
|
50
|
+
// itself sets `args = [entry.get("ctx")]`), so moving the assertion from
|
|
51
|
+
// `ctx` to `args.0` reads the SAME map, post-call, and preserves every
|
|
52
|
+
// leaf: nothing is dropped, weakened or skipped. `retargetctx` below does
|
|
53
|
+
// that rewrite on the spec handed to the engine. Swift faces the identical
|
|
54
|
+
// problem and answers it identically; the upstream fix is for the Rust
|
|
55
|
+
// port's `drive` to re-point `entry.ctx` at the returned `args[0]`, the
|
|
56
|
+
// way JS object identity does implicitly — filed as a follow-up, not
|
|
57
|
+
// worked around by editing a vendored file.
|
|
58
|
+
//
|
|
59
|
+
// 4. NUMBERS NEED NOTHING. omni's parser reads every JSON number as `f64`
|
|
60
|
+
// and this port's `Value::Num` is also `f64` — unlike go/csharp/java,
|
|
61
|
+
// where an integral double had to be narrowed before a subject saw it.
|
|
62
|
+
//
|
|
63
|
+
// 5. KEY ORDER. omni models a map as a `BTreeMap`, which sorts; this port's
|
|
64
|
+
// `OrderedMap` preserves insertion order. Every map in the shared corpus
|
|
65
|
+
// is already in sorted key order, so the round-trip is lossless over it —
|
|
66
|
+
// but an out-of-order map authored later WOULD be reordered on the way
|
|
67
|
+
// in, and `raw_unsorted_keys` below is the tripwire that says so instead
|
|
68
|
+
// of failing an order-sensitive subject (`keysof`, `items`, `stringify`)
|
|
69
|
+
// with a mystery diff. It reads the corpus FILE with its own
|
|
70
|
+
// order-preserving scanner and never touches `Json`: a check fed by
|
|
71
|
+
// omni's parser would be comparing an already-sorted map against itself
|
|
72
|
+
// and could not fail. See `corpus_maps_are_in_sorted_key_order`.
|
|
73
|
+
//
|
|
74
|
+
// 7. WHAT RAN IS COUNTED, NOT WHAT WAS DECLARED. `drive` counts SUBJECT
|
|
75
|
+
// INVOCATIONS, not `entrycount(set)`: a number derived from the spec
|
|
76
|
+
// cannot tell a working engine from a disconnected one, and would read as
|
|
77
|
+
// evidence while proving nothing. It also compares the two and fails the
|
|
78
|
+
// group when they differ. `report` then refuses to pass on a group that
|
|
79
|
+
// is absent from the corpus, or present in the corpus but driven by
|
|
80
|
+
// nothing — the two ways a suite quietly stops checking.
|
|
81
|
+
//
|
|
82
|
+
// 6. FAILURES ARE ACCUMULATED, NOT RAISED. omni stops a group at its first
|
|
83
|
+
// bad entry and returns an `OmniError`; the struct suite reports the whole
|
|
84
|
+
// corpus in one panic at the end. `drive` records the message and carries
|
|
85
|
+
// on, so one run still names every broken GROUP.
|
|
86
|
+
|
|
87
|
+
#![allow(dead_code)]
|
|
88
|
+
// The vendored port re-exports its whole surface; a test crate uses part of
|
|
89
|
+
// it, and the rest must not warn. The attributes go on the module
|
|
90
|
+
// DECLARATION - a vendored file is never edited.
|
|
91
|
+
#![allow(unused_imports)]
|
|
92
|
+
|
|
93
|
+
#[path = "../vendor/omni/mod.rs"]
|
|
94
|
+
pub mod omni;
|
|
95
|
+
|
|
96
|
+
use std::collections::BTreeMap;
|
|
97
|
+
use std::path::PathBuf;
|
|
98
|
+
use std::rc::Rc;
|
|
99
|
+
|
|
100
|
+
pub use omni::json::Json;
|
|
101
|
+
pub use omni::runner::{Flags, OmniError, Provider, RunPack, SpecRef, Subject, SubjectArgs};
|
|
102
|
+
pub use omni::util::{EXISTSMARK, NULLMARK, UNDEFMARK};
|
|
103
|
+
|
|
104
|
+
use RUSTCRATE::utility::voxgigstruct::ordered_map::OrderedMap;
|
|
105
|
+
use RUSTCRATE::utility::voxgigstruct::value::Value;
|
|
106
|
+
use RUSTCRATE::utility::voxgigstruct::InjectDef;
|
|
107
|
+
use RUSTCRATE::ProjectNameError;
|
|
108
|
+
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
// The two value models (decision 1)
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
|
|
113
|
+
/// omni's model -> this SDK's.
|
|
114
|
+
pub fn tostruct(val: &Json) -> Value {
|
|
115
|
+
match val {
|
|
116
|
+
Json::Absent => Value::Noval,
|
|
117
|
+
Json::Null => Value::Null,
|
|
118
|
+
Json::Bool(flag) => Value::Bool(*flag),
|
|
119
|
+
Json::Num(num) => Value::Num(*num),
|
|
120
|
+
Json::Str(text) => Value::Str(text.clone()),
|
|
121
|
+
Json::List(items) => Value::list(items.iter().map(tostruct).collect()),
|
|
122
|
+
Json::Map(entries) => {
|
|
123
|
+
let mut map = OrderedMap::new();
|
|
124
|
+
for (key, entry) in entries.iter() {
|
|
125
|
+
map.insert(key.clone(), tostruct(entry));
|
|
126
|
+
}
|
|
127
|
+
Value::map(map)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/// This SDK's model -> omni's.
|
|
133
|
+
///
|
|
134
|
+
/// `Value::Func` has no JSON shape at all. It reaches here only when a corpus
|
|
135
|
+
/// entry puts a callable in data (`get_elem` with a callable `alt`, `$APPLY`,
|
|
136
|
+
/// a user `$FORMAT`), and in every such case the corpus asserts on what the
|
|
137
|
+
/// call RETURNED, not on the callable. `Json::Absent` is the honest answer:
|
|
138
|
+
/// it is what omni's own model says about a value that is not JSON, and
|
|
139
|
+
/// omni's `fixjson` then renders it as NULLMARK under the null flag — the
|
|
140
|
+
/// same place the retired hand-written `fix_json` put it.
|
|
141
|
+
pub fn toomni(val: &Value) -> Json {
|
|
142
|
+
match val {
|
|
143
|
+
Value::Noval => Json::Absent,
|
|
144
|
+
Value::Null => Json::Null,
|
|
145
|
+
Value::Bool(flag) => Json::Bool(*flag),
|
|
146
|
+
Value::Num(num) => Json::Num(*num),
|
|
147
|
+
Value::Str(text) => Json::Str(text.clone()),
|
|
148
|
+
Value::List(items) => Json::List(items.borrow().iter().map(toomni).collect()),
|
|
149
|
+
Value::Map(entries) => {
|
|
150
|
+
let mut map = BTreeMap::new();
|
|
151
|
+
for (key, entry) in entries.borrow().iter() {
|
|
152
|
+
map.insert(key.clone(), toomni(entry));
|
|
153
|
+
}
|
|
154
|
+
Json::Map(map)
|
|
155
|
+
}
|
|
156
|
+
Value::Func(_) => Json::Absent,
|
|
157
|
+
Value::Sentinel(_) => Json::Absent,
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/// The tripwire for decision 5: how many maps the raw corpus scan inspected,
|
|
162
|
+
/// and the first one whose keys are NOT in sorted order.
|
|
163
|
+
pub struct KeyOrderScan {
|
|
164
|
+
/// Maps inspected. Reported so a scan that read nothing cannot pass as a
|
|
165
|
+
/// scan that found nothing.
|
|
166
|
+
pub maps: usize,
|
|
167
|
+
/// `<dotted path>: [keys as authored]` for the first offender.
|
|
168
|
+
pub unsorted: Option<String>,
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/// Scan RAW JSON TEXT for a map whose keys are not in sorted order.
|
|
172
|
+
///
|
|
173
|
+
/// This deliberately does NOT go through `omni::runner::loadspec`: omni's
|
|
174
|
+
/// `Json::Map` is a `BTreeMap`, so a parse has already sorted every map and
|
|
175
|
+
/// the disorder this exists to catch is gone before the check can see it. A
|
|
176
|
+
/// tripwire fed by the thing it is watching cannot fire, so the scanner
|
|
177
|
+
/// below walks the file itself and keeps keys in the order they were
|
|
178
|
+
/// authored. `String`'s ordering is byte-lexicographic on UTF-8, which is
|
|
179
|
+
/// exactly the ordering a `BTreeMap<String, _>` imposes, so a sorted scan
|
|
180
|
+
/// means a lossless crossing.
|
|
181
|
+
///
|
|
182
|
+
/// Panics on malformed JSON: a corpus this cannot parse must be loud, not a
|
|
183
|
+
/// silent zero-map pass.
|
|
184
|
+
pub fn raw_unsorted_keys(text: &str) -> KeyOrderScan {
|
|
185
|
+
let mut scan = RawScan {
|
|
186
|
+
src: text.as_bytes(),
|
|
187
|
+
pos: 0,
|
|
188
|
+
maps: 0,
|
|
189
|
+
path: Vec::new(),
|
|
190
|
+
unsorted: None,
|
|
191
|
+
};
|
|
192
|
+
scan.ws();
|
|
193
|
+
scan.value();
|
|
194
|
+
scan.ws();
|
|
195
|
+
if scan.pos != scan.src.len() {
|
|
196
|
+
scan.bail("trailing input after the top-level value");
|
|
197
|
+
}
|
|
198
|
+
KeyOrderScan {
|
|
199
|
+
maps: scan.maps,
|
|
200
|
+
unsorted: scan.unsorted,
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/// A structure-only JSON reader: it builds no values, it only walks the text
|
|
205
|
+
/// and records the key order of every object it passes through.
|
|
206
|
+
struct RawScan<'a> {
|
|
207
|
+
src: &'a [u8],
|
|
208
|
+
pos: usize,
|
|
209
|
+
maps: usize,
|
|
210
|
+
path: Vec<String>,
|
|
211
|
+
unsorted: Option<String>,
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
impl<'a> RawScan<'a> {
|
|
215
|
+
fn bail(&self, why: &str) -> ! {
|
|
216
|
+
panic!(
|
|
217
|
+
"corpus key-order scan: {} at byte {} (path {:?})",
|
|
218
|
+
why,
|
|
219
|
+
self.pos,
|
|
220
|
+
self.path.join(".")
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
fn peek(&self) -> u8 {
|
|
225
|
+
if self.pos < self.src.len() {
|
|
226
|
+
self.src[self.pos]
|
|
227
|
+
} else {
|
|
228
|
+
0
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
fn ws(&mut self) {
|
|
233
|
+
while self.pos < self.src.len() {
|
|
234
|
+
match self.src[self.pos] {
|
|
235
|
+
b' ' | b'\t' | b'\n' | b'\r' => self.pos += 1,
|
|
236
|
+
_ => break,
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
fn expect(&mut self, want: u8) {
|
|
242
|
+
if self.peek() != want {
|
|
243
|
+
self.bail(&format!("expected {:?}", want as char));
|
|
244
|
+
}
|
|
245
|
+
self.pos += 1;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
fn value(&mut self) {
|
|
249
|
+
match self.peek() {
|
|
250
|
+
b'{' => self.object(),
|
|
251
|
+
b'[' => self.array(),
|
|
252
|
+
b'"' => {
|
|
253
|
+
self.string();
|
|
254
|
+
}
|
|
255
|
+
b't' => self.literal(b"true"),
|
|
256
|
+
b'f' => self.literal(b"false"),
|
|
257
|
+
b'n' => self.literal(b"null"),
|
|
258
|
+
b'-' | b'0'..=b'9' => self.number(),
|
|
259
|
+
_ => self.bail("not a JSON value"),
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
fn literal(&mut self, want: &[u8]) {
|
|
264
|
+
if self.src.len() < self.pos + want.len() || &self.src[self.pos..self.pos + want.len()] != want {
|
|
265
|
+
self.bail("bad literal");
|
|
266
|
+
}
|
|
267
|
+
self.pos += want.len();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
fn number(&mut self) {
|
|
271
|
+
let start = self.pos;
|
|
272
|
+
while self.pos < self.src.len() {
|
|
273
|
+
match self.src[self.pos] {
|
|
274
|
+
b'-' | b'+' | b'.' | b'e' | b'E' | b'0'..=b'9' => self.pos += 1,
|
|
275
|
+
_ => break,
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
if start == self.pos {
|
|
279
|
+
self.bail("empty number");
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/// A JSON string, unescaped — a key must be compared as the DECODED text,
|
|
284
|
+
/// which is what a `BTreeMap` would hold.
|
|
285
|
+
fn string(&mut self) -> String {
|
|
286
|
+
self.expect(b'"');
|
|
287
|
+
let mut out = String::new();
|
|
288
|
+
loop {
|
|
289
|
+
if self.pos >= self.src.len() {
|
|
290
|
+
self.bail("unterminated string");
|
|
291
|
+
}
|
|
292
|
+
let byte = self.src[self.pos];
|
|
293
|
+
self.pos += 1;
|
|
294
|
+
match byte {
|
|
295
|
+
b'"' => return out,
|
|
296
|
+
b'\\' => {
|
|
297
|
+
if self.pos >= self.src.len() {
|
|
298
|
+
self.bail("unterminated escape");
|
|
299
|
+
}
|
|
300
|
+
let esc = self.src[self.pos];
|
|
301
|
+
self.pos += 1;
|
|
302
|
+
match esc {
|
|
303
|
+
b'"' => out.push('"'),
|
|
304
|
+
b'\\' => out.push('\\'),
|
|
305
|
+
b'/' => out.push('/'),
|
|
306
|
+
b'b' => out.push('\u{8}'),
|
|
307
|
+
b'f' => out.push('\u{c}'),
|
|
308
|
+
b'n' => out.push('\n'),
|
|
309
|
+
b'r' => out.push('\r'),
|
|
310
|
+
b't' => out.push('\t'),
|
|
311
|
+
b'u' => {
|
|
312
|
+
let code = self.hex4();
|
|
313
|
+
// A surrogate pair is two \u escapes; the corpus has
|
|
314
|
+
// none, but decode them rather than mis-order one.
|
|
315
|
+
if (0xD800..0xDC00).contains(&code) {
|
|
316
|
+
if b'\\' == self.peek() {
|
|
317
|
+
self.pos += 1;
|
|
318
|
+
self.expect(b'u');
|
|
319
|
+
let low = self.hex4();
|
|
320
|
+
let joined =
|
|
321
|
+
0x10000 + ((code - 0xD800) << 10) + (low - 0xDC00);
|
|
322
|
+
out.push(
|
|
323
|
+
char::from_u32(joined)
|
|
324
|
+
.unwrap_or_else(|| self.bail("bad surrogate pair")),
|
|
325
|
+
);
|
|
326
|
+
} else {
|
|
327
|
+
self.bail("lone high surrogate");
|
|
328
|
+
}
|
|
329
|
+
} else {
|
|
330
|
+
out.push(
|
|
331
|
+
char::from_u32(code)
|
|
332
|
+
.unwrap_or_else(|| self.bail("bad \\u escape")),
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
_ => self.bail("unknown escape"),
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
_ => {
|
|
340
|
+
// Copy the whole UTF-8 sequence, not just its lead byte.
|
|
341
|
+
let width = utf8width(byte);
|
|
342
|
+
let end = self.pos - 1 + width;
|
|
343
|
+
if self.src.len() < end {
|
|
344
|
+
self.bail("truncated UTF-8 in string");
|
|
345
|
+
}
|
|
346
|
+
match std::str::from_utf8(&self.src[self.pos - 1..end]) {
|
|
347
|
+
Ok(text) => out.push_str(text),
|
|
348
|
+
Err(_) => self.bail("invalid UTF-8 in string"),
|
|
349
|
+
}
|
|
350
|
+
self.pos = end;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
fn hex4(&mut self) -> u32 {
|
|
357
|
+
if self.src.len() < self.pos + 4 {
|
|
358
|
+
self.bail("truncated \\u escape");
|
|
359
|
+
}
|
|
360
|
+
let text = std::str::from_utf8(&self.src[self.pos..self.pos + 4])
|
|
361
|
+
.unwrap_or_else(|_| self.bail("bad \\u escape"));
|
|
362
|
+
let code = u32::from_str_radix(text, 16).unwrap_or_else(|_| self.bail("bad \\u escape"));
|
|
363
|
+
self.pos += 4;
|
|
364
|
+
code
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
fn array(&mut self) {
|
|
368
|
+
self.expect(b'[');
|
|
369
|
+
self.ws();
|
|
370
|
+
if b']' == self.peek() {
|
|
371
|
+
self.pos += 1;
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
let mut index = 0usize;
|
|
375
|
+
loop {
|
|
376
|
+
self.path.push(index.to_string());
|
|
377
|
+
self.ws();
|
|
378
|
+
self.value();
|
|
379
|
+
self.path.pop();
|
|
380
|
+
self.ws();
|
|
381
|
+
match self.peek() {
|
|
382
|
+
b',' => {
|
|
383
|
+
self.pos += 1;
|
|
384
|
+
index += 1;
|
|
385
|
+
}
|
|
386
|
+
b']' => {
|
|
387
|
+
self.pos += 1;
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
_ => self.bail("expected ',' or ']'"),
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
fn object(&mut self) {
|
|
396
|
+
self.expect(b'{');
|
|
397
|
+
self.maps += 1;
|
|
398
|
+
let mut keys: Vec<String> = Vec::new();
|
|
399
|
+
self.ws();
|
|
400
|
+
if b'}' == self.peek() {
|
|
401
|
+
self.pos += 1;
|
|
402
|
+
self.checkorder(&keys);
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
loop {
|
|
406
|
+
self.ws();
|
|
407
|
+
let key = self.string();
|
|
408
|
+
keys.push(key.clone());
|
|
409
|
+
self.ws();
|
|
410
|
+
self.expect(b':');
|
|
411
|
+
self.ws();
|
|
412
|
+
self.path.push(key);
|
|
413
|
+
self.value();
|
|
414
|
+
self.path.pop();
|
|
415
|
+
self.ws();
|
|
416
|
+
match self.peek() {
|
|
417
|
+
b',' => self.pos += 1,
|
|
418
|
+
b'}' => {
|
|
419
|
+
self.pos += 1;
|
|
420
|
+
self.checkorder(&keys);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
_ => self.bail("expected ',' or '}'"),
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
fn checkorder(&mut self, keys: &[String]) {
|
|
429
|
+
if self.unsorted.is_some() {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
let mut sorted = keys.to_vec();
|
|
433
|
+
sorted.sort();
|
|
434
|
+
if keys != sorted.as_slice() {
|
|
435
|
+
self.unsorted = Some(format!("{}: {:?}", self.path.join("."), keys));
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
fn utf8width(lead: u8) -> usize {
|
|
441
|
+
if 0xF0 <= lead {
|
|
442
|
+
4
|
|
443
|
+
} else if 0xE0 <= lead {
|
|
444
|
+
3
|
|
445
|
+
} else if 0xC0 <= lead {
|
|
446
|
+
2
|
|
447
|
+
} else {
|
|
448
|
+
1
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// ---------------------------------------------------------------------------
|
|
453
|
+
// Spec access
|
|
454
|
+
// ---------------------------------------------------------------------------
|
|
455
|
+
|
|
456
|
+
/// The shared corpus, compiled by the project build. `CARGO_MANIFEST_DIR` is
|
|
457
|
+
/// the SDK's own `rust/` directory, and the corpus sits beside it.
|
|
458
|
+
pub fn spec_path() -> String {
|
|
459
|
+
let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
|
460
|
+
path.push("..");
|
|
461
|
+
path.push(".sdk");
|
|
462
|
+
path.push("test");
|
|
463
|
+
path.push("test.json");
|
|
464
|
+
path.to_string_lossy().into_owned()
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/// The whole corpus, as omni loaded it.
|
|
468
|
+
pub fn corpus() -> Json {
|
|
469
|
+
omni::runner::loadspec(SpecRef::Path(spec_path()))
|
|
470
|
+
.unwrap_or_else(|err| panic!("omni: {}", err.message))
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/// A child node by key (absent when missing).
|
|
474
|
+
pub fn jget(val: &Json, key: &str) -> Json {
|
|
475
|
+
val.get(key)
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/// A child node by path.
|
|
479
|
+
pub fn jpath(val: &Json, keys: &[&str]) -> Json {
|
|
480
|
+
let mut current = val.clone();
|
|
481
|
+
for key in keys {
|
|
482
|
+
current = current.get(key);
|
|
483
|
+
}
|
|
484
|
+
current
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/// How many entries a group declares.
|
|
488
|
+
pub fn entrycount(set: &Json) -> usize {
|
|
489
|
+
set.get("set").aslist().map(|list| list.len()).unwrap_or(0)
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// ---------------------------------------------------------------------------
|
|
493
|
+
// The runner
|
|
494
|
+
// ---------------------------------------------------------------------------
|
|
495
|
+
|
|
496
|
+
/// What the runner returns for one named spec section — the struct-runner
|
|
497
|
+
/// shape the corpus call sites consume.
|
|
498
|
+
pub struct Run {
|
|
499
|
+
pack: RunPack,
|
|
500
|
+
/// The whole corpus (sections outside this one: `DEF` blocks, the
|
|
501
|
+
/// `primary/check` client group the struct suite drives by hand).
|
|
502
|
+
pub all: Json,
|
|
503
|
+
/// The resolved section.
|
|
504
|
+
pub spec: Json,
|
|
505
|
+
pub failures: Vec<String>,
|
|
506
|
+
pub passed: usize,
|
|
507
|
+
/// Groups absent from THIS SDK's corpus subset, named so a run reports
|
|
508
|
+
/// what it did not check rather than passing in silence. `report`
|
|
509
|
+
/// FAILS on any name here that the suite did not declare expected.
|
|
510
|
+
pub skipped: Vec<String>,
|
|
511
|
+
/// Every group label the suite ASKED for, present or absent. `report`
|
|
512
|
+
/// checks it against the groups the corpus actually carries, so a
|
|
513
|
+
/// corpus group that nothing drives is a failure rather than a silence.
|
|
514
|
+
pub driven: Vec<String>,
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
impl Run {
|
|
518
|
+
/// A runner over one named section of the shared corpus.
|
|
519
|
+
pub fn section(name: &str) -> Run {
|
|
520
|
+
Run::over(corpus(), name)
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/// A runner over an in-memory spec — omni's own capability, which keeps
|
|
524
|
+
/// the smoke test free of a fixture file.
|
|
525
|
+
pub fn over(all: Json, name: &str) -> Run {
|
|
526
|
+
let runner = omni::runner::make_runner(all.clone(), Provider::default())
|
|
527
|
+
.unwrap_or_else(|err| panic!("omni: {}", err.message));
|
|
528
|
+
let pack = runner
|
|
529
|
+
.runner(name, None)
|
|
530
|
+
.unwrap_or_else(|err| panic!("omni: {}", err.message));
|
|
531
|
+
|
|
532
|
+
Run {
|
|
533
|
+
spec: pack.spec.clone(),
|
|
534
|
+
pack,
|
|
535
|
+
all,
|
|
536
|
+
failures: Vec::new(),
|
|
537
|
+
passed: 0,
|
|
538
|
+
skipped: Vec::new(),
|
|
539
|
+
driven: Vec::new(),
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
/// A named group of the resolved section.
|
|
544
|
+
pub fn set(&self, keys: &[&str]) -> Json {
|
|
545
|
+
jpath(&self.spec, keys)
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
/// Run one group whose subject cannot fail.
|
|
549
|
+
pub fn run_set<F>(&mut self, set: &Json, nullflag: bool, label: &str, subject: F)
|
|
550
|
+
where
|
|
551
|
+
F: FnMut(Value) -> Value + 'static,
|
|
552
|
+
{
|
|
553
|
+
let cell = Rc::new(std::cell::RefCell::new(subject));
|
|
554
|
+
self.drive(set, nullflag, label, move |args: &mut [Json]| {
|
|
555
|
+
let input = tostruct(args.first().unwrap_or(&Json::Absent));
|
|
556
|
+
let result = (cell.borrow_mut())(input.clone());
|
|
557
|
+
writeback(args, 0, &input);
|
|
558
|
+
Ok(toomni(&result))
|
|
559
|
+
});
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
/// Run one group whose subject may fail, which the corpus asserts on
|
|
563
|
+
/// with `err`.
|
|
564
|
+
pub fn run_set_fallible<F>(&mut self, set: &Json, nullflag: bool, label: &str, subject: F)
|
|
565
|
+
where
|
|
566
|
+
F: FnMut(Value) -> Result<Value, String> + 'static,
|
|
567
|
+
{
|
|
568
|
+
let cell = Rc::new(std::cell::RefCell::new(subject));
|
|
569
|
+
self.drive(set, nullflag, label, move |args: &mut [Json]| {
|
|
570
|
+
let input = tostruct(args.first().unwrap_or(&Json::Absent));
|
|
571
|
+
let result = (cell.borrow_mut())(input.clone());
|
|
572
|
+
writeback(args, 0, &input);
|
|
573
|
+
result.map(|val| toomni(&val))
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/// Run one group whose subject takes omni's whole argument list and may
|
|
578
|
+
/// fail with an SDK error. This is the shape the `primary` suite needs:
|
|
579
|
+
/// a `ctx` entry arrives as `args[0]`, a MAP, which the call site turns
|
|
580
|
+
/// into a typed `Context` and writes observable state back into
|
|
581
|
+
/// (decisions 2 and 3).
|
|
582
|
+
pub fn run_set_args<F>(&mut self, set: &Json, nullflag: bool, label: &str, subject: F)
|
|
583
|
+
where
|
|
584
|
+
F: FnMut(&mut Vec<Value>) -> Result<Value, ProjectNameError> + 'static,
|
|
585
|
+
{
|
|
586
|
+
let cell = Rc::new(std::cell::RefCell::new(subject));
|
|
587
|
+
self.drive(set, nullflag, label, move |args: &mut [Json]| {
|
|
588
|
+
let mut input: Vec<Value> = args.iter().map(tostruct).collect();
|
|
589
|
+
let result = (cell.borrow_mut())(&mut input);
|
|
590
|
+
for (index, val) in input.iter().enumerate() {
|
|
591
|
+
writeback(args, index, val);
|
|
592
|
+
}
|
|
593
|
+
result.map(|val| toomni(&val)).map_err(|err| err.msg)
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/// Hand one group to omni and record the outcome.
|
|
598
|
+
fn drive<F>(&mut self, set: &Json, nullflag: bool, label: &str, subject: F)
|
|
599
|
+
where
|
|
600
|
+
F: Fn(&mut [Json]) -> Result<Json, String> + 'static,
|
|
601
|
+
{
|
|
602
|
+
self.driven.push(label.to_string());
|
|
603
|
+
|
|
604
|
+
// A section this SDK's corpus subset does not carry. Named, not
|
|
605
|
+
// silent: `report` fails unless the suite declared this skip.
|
|
606
|
+
if set.isabsent() {
|
|
607
|
+
self.skipped.push(label.to_string());
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
let flags = Flags {
|
|
612
|
+
null: nullflag,
|
|
613
|
+
name: Some(label.to_string()),
|
|
614
|
+
};
|
|
615
|
+
let count = entrycount(set);
|
|
616
|
+
let usespec = retargetctx(set);
|
|
617
|
+
|
|
618
|
+
// Decision 7: count SUBJECT INVOCATIONS. `entrycount` says what the
|
|
619
|
+
// corpus declares, which a disconnected engine would report just as
|
|
620
|
+
// happily; this says what actually reached a subject.
|
|
621
|
+
let calls = Rc::new(std::cell::Cell::new(0usize));
|
|
622
|
+
let seen = calls.clone();
|
|
623
|
+
let usesubject: SubjectArgs = Rc::new(move |args: &mut [Json]| {
|
|
624
|
+
seen.set(seen.get() + 1);
|
|
625
|
+
subject(args)
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
match self.pack.runsetflags_args(&usespec, &flags, &usesubject) {
|
|
629
|
+
Ok(()) => {
|
|
630
|
+
let ran = calls.get();
|
|
631
|
+
if ran != count {
|
|
632
|
+
self.failures.push(format!(
|
|
633
|
+
"{}: the engine reported success after running {} of the {} \
|
|
634
|
+
entries the corpus declares",
|
|
635
|
+
label, ran, count
|
|
636
|
+
));
|
|
637
|
+
}
|
|
638
|
+
self.passed += ran;
|
|
639
|
+
}
|
|
640
|
+
Err(err) => self.failures.push(err.message.replace('\n', " | ")),
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/// Every `<category>-<group>` in this section that carries a non-empty
|
|
645
|
+
/// `set` — the groups a suite over this section is expected to drive.
|
|
646
|
+
///
|
|
647
|
+
/// Shape-specific: it assumes the `struct` section's two levels
|
|
648
|
+
/// (`<category>.<group>.set`) and the `"<category>-<group>"` labels the
|
|
649
|
+
/// struct suite passes to `run_set`. The `primary` section nests
|
|
650
|
+
/// differently (`primary.<name>.basic`) and labels its groups `<name>`,
|
|
651
|
+
/// so it guards zero-case runs in `runsection` instead — see
|
|
652
|
+
/// tests/primary_utility_test.rs.
|
|
653
|
+
pub fn corpus_groups(&self) -> Vec<(String, usize)> {
|
|
654
|
+
let mut found: Vec<(String, usize)> = Vec::new();
|
|
655
|
+
let categories = match self.spec.asmap() {
|
|
656
|
+
Some(map) => map,
|
|
657
|
+
None => return found,
|
|
658
|
+
};
|
|
659
|
+
for (category, node) in categories.iter() {
|
|
660
|
+
let groups = match node.asmap() {
|
|
661
|
+
Some(map) => map,
|
|
662
|
+
// `<category>.name` is a string and `<category>.set` an empty
|
|
663
|
+
// list; neither is a group.
|
|
664
|
+
None => continue,
|
|
665
|
+
};
|
|
666
|
+
for (name, group) in groups.iter() {
|
|
667
|
+
let count = entrycount(group);
|
|
668
|
+
if group.ismap() && 0 < count {
|
|
669
|
+
found.push((format!("{}-{}", category, name), count));
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
found
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
/// Fail the test with every accumulated failure, or report the count.
|
|
677
|
+
///
|
|
678
|
+
/// `expectedskips` names the groups THIS SDK's corpus subset does not
|
|
679
|
+
/// carry. It is exhaustive in both directions: a group that goes absent
|
|
680
|
+
/// without being listed fails, and a listed group that is no longer
|
|
681
|
+
/// absent fails too. Without that a renamed or deleted group would take
|
|
682
|
+
/// its whole check count with it and the suite would still say `ok` —
|
|
683
|
+
/// the exact silence the shared oracle exists to prevent.
|
|
684
|
+
pub fn report(&self, what: &str, expectedskips: &[&str]) {
|
|
685
|
+
let mut problems: Vec<String> = self.failures.clone();
|
|
686
|
+
|
|
687
|
+
for label in self.skipped.iter() {
|
|
688
|
+
if !expectedskips.contains(&label.as_str()) {
|
|
689
|
+
problems.push(format!(
|
|
690
|
+
"{}: ABSENT from the corpus, so it ran ZERO checks — a renamed or \
|
|
691
|
+
deleted group. Restore it, or add it to the expected-skip list.",
|
|
692
|
+
label
|
|
693
|
+
));
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
for label in expectedskips.iter() {
|
|
697
|
+
if !self.skipped.iter().any(|name| name == label) {
|
|
698
|
+
problems.push(format!(
|
|
699
|
+
"{}: listed as an expected skip but was not skipped — either the \
|
|
700
|
+
corpus now carries it (drop it from the expected-skip list) or the \
|
|
701
|
+
suite stopped asking for it.",
|
|
702
|
+
label
|
|
703
|
+
));
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
for (label, count) in self.corpus_groups() {
|
|
707
|
+
if !self.driven.iter().any(|name| *name == label) {
|
|
708
|
+
problems.push(format!(
|
|
709
|
+
"{}: the corpus carries this group ({} entries) but NOTHING in this \
|
|
710
|
+
suite drives it — wire up a subject, or the entries are dead weight.",
|
|
711
|
+
label, count
|
|
712
|
+
));
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
if !problems.is_empty() {
|
|
717
|
+
let total = problems.len();
|
|
718
|
+
let mut message = format!(
|
|
719
|
+
"\n{} corpus problem(s) ({} checks actually ran):\n",
|
|
720
|
+
total, self.passed
|
|
721
|
+
);
|
|
722
|
+
for problem in problems.iter().take(60) {
|
|
723
|
+
message.push_str(" - ");
|
|
724
|
+
message.push_str(problem);
|
|
725
|
+
message.push('\n');
|
|
726
|
+
}
|
|
727
|
+
if 60 < total {
|
|
728
|
+
message.push_str(&format!(" ... and {} more\n", total - 60));
|
|
729
|
+
}
|
|
730
|
+
panic!("{message}");
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
if !self.skipped.is_empty() {
|
|
734
|
+
eprintln!(
|
|
735
|
+
"{}: skipped (declared absent from this corpus subset): {:?}",
|
|
736
|
+
what, self.skipped
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
eprintln!("{}: {} checks passed", what, self.passed);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
/// Write one converted argument back into omni's own slice (decision 2).
|
|
744
|
+
fn writeback(args: &mut [Json], index: usize, val: &Value) {
|
|
745
|
+
if let Some(slot) = args.get_mut(index) {
|
|
746
|
+
*slot = toomni(val);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/// Retarget `match: {ctx: ...}` onto `match: {args: {"0": ...}}` — decision 3.
|
|
751
|
+
/// Only when the entry HAS a ctx or args (so args[0] is that map) and the
|
|
752
|
+
/// check does not already assert on `args`.
|
|
753
|
+
fn retargetctx(testspec: &Json) -> Json {
|
|
754
|
+
let set = match testspec.get("set") {
|
|
755
|
+
Json::List(list) => list,
|
|
756
|
+
_ => return testspec.clone(),
|
|
757
|
+
};
|
|
758
|
+
|
|
759
|
+
let mut out: Vec<Json> = Vec::with_capacity(set.len());
|
|
760
|
+
for rawentry in set.iter() {
|
|
761
|
+
let check = rawentry.get("match");
|
|
762
|
+
if rawentry.ismap()
|
|
763
|
+
&& check.ismap()
|
|
764
|
+
&& check.has("ctx")
|
|
765
|
+
&& !check.has("args")
|
|
766
|
+
&& (rawentry.has("ctx") || rawentry.has("args"))
|
|
767
|
+
{
|
|
768
|
+
let mut newcheck = BTreeMap::new();
|
|
769
|
+
if let Json::Map(fields) = &check {
|
|
770
|
+
for (key, val) in fields.iter() {
|
|
771
|
+
// Drop the original leaf: it would read the stale
|
|
772
|
+
// pre-call copy omni keeps in `entry.ctx`.
|
|
773
|
+
if "ctx" != key {
|
|
774
|
+
newcheck.insert(key.clone(), val.clone());
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
let mut byindex = BTreeMap::new();
|
|
779
|
+
byindex.insert("0".to_string(), check.get("ctx"));
|
|
780
|
+
newcheck.insert("args".to_string(), Json::Map(byindex));
|
|
781
|
+
|
|
782
|
+
let mut entry = BTreeMap::new();
|
|
783
|
+
if let Json::Map(fields) = rawentry {
|
|
784
|
+
for (key, val) in fields.iter() {
|
|
785
|
+
entry.insert(key.clone(), val.clone());
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
entry.insert("match".to_string(), Json::Map(newcheck));
|
|
789
|
+
out.push(Json::Map(entry));
|
|
790
|
+
continue;
|
|
791
|
+
}
|
|
792
|
+
out.push(rawentry.clone());
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
let mut spec = BTreeMap::new();
|
|
796
|
+
if let Json::Map(fields) = testspec {
|
|
797
|
+
for (key, val) in fields.iter() {
|
|
798
|
+
spec.insert(key.clone(), val.clone());
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
spec.insert("set".to_string(), Json::List(out));
|
|
802
|
+
Json::Map(spec)
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// ---------------------------------------------------------------------------
|
|
806
|
+
// Corpus-entry helpers, retained from the retired struct_runner
|
|
807
|
+
// ---------------------------------------------------------------------------
|
|
808
|
+
|
|
809
|
+
/// Raw field extraction from a corpus entry, in this SDK's value model:
|
|
810
|
+
/// preserves a stored JSON null so a field declared `null` (`{val: null}`)
|
|
811
|
+
/// reaches the subject as `Value::Null` and is not silently dropped.
|
|
812
|
+
pub fn vget(val: &Value, key: &str) -> Value {
|
|
813
|
+
RUSTCRATE::utility::voxgigstruct::lookup(val, &Value::str(key))
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
pub fn vget_path(val: &Value, keys: &[&str]) -> Value {
|
|
817
|
+
let mut current = val.clone();
|
|
818
|
+
for key in keys {
|
|
819
|
+
current = vget(¤t, key);
|
|
820
|
+
}
|
|
821
|
+
current
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
pub fn as_i64_opt(val: &Value) -> Option<i64> {
|
|
825
|
+
match val {
|
|
826
|
+
Value::Num(num) => Some(*num as i64),
|
|
827
|
+
_ => None,
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
pub fn as_str_opt(val: &Value) -> Option<String> {
|
|
832
|
+
match val {
|
|
833
|
+
Value::Str(text) => Some(text.clone()),
|
|
834
|
+
_ => None,
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
pub fn b(flag: bool) -> Value {
|
|
839
|
+
Value::Bool(flag)
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
/// The `fixjson` of the corpus's own comparison boundary, for the handful of
|
|
843
|
+
/// corpus nodes that are a single `{in, out}` object rather than a `set` and
|
|
844
|
+
/// so never reach omni (`merge/basic`, `inject/basic`, `transform/basic`,
|
|
845
|
+
/// `walk/log`). omni does exactly this to everything it runs.
|
|
846
|
+
pub fn fix_json(val: &Value, nullflag: bool) -> Value {
|
|
847
|
+
tostruct(&omni::runner::fixjson(
|
|
848
|
+
&toomni(val),
|
|
849
|
+
&Flags {
|
|
850
|
+
null: nullflag,
|
|
851
|
+
name: None,
|
|
852
|
+
},
|
|
853
|
+
))
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
pub fn inject_def_from_value(val: &Value) -> InjectDef {
|
|
857
|
+
let mut def = InjectDef::default();
|
|
858
|
+
if let Value::Map(_) = val {
|
|
859
|
+
let key = vget(val, "key");
|
|
860
|
+
if !key.is_noval() {
|
|
861
|
+
def.key = Some(key);
|
|
862
|
+
}
|
|
863
|
+
let meta = vget(val, "meta");
|
|
864
|
+
if !meta.is_noval() {
|
|
865
|
+
def.meta = Some(meta);
|
|
866
|
+
}
|
|
867
|
+
let base = vget(val, "base");
|
|
868
|
+
if let Value::Str(text) = base {
|
|
869
|
+
def.base = Some(text);
|
|
870
|
+
}
|
|
871
|
+
let dparent = vget(val, "dparent");
|
|
872
|
+
if !dparent.is_noval() {
|
|
873
|
+
def.dparent = Some(dparent);
|
|
874
|
+
}
|
|
875
|
+
let dpath = vget(val, "dpath");
|
|
876
|
+
if let Value::Str(text) = dpath {
|
|
877
|
+
def.dpath = Some(text.split('.').map(|part| part.to_string()).collect());
|
|
878
|
+
} else if let Value::List(list) = &dpath {
|
|
879
|
+
def.dpath = Some(
|
|
880
|
+
list.borrow()
|
|
881
|
+
.iter()
|
|
882
|
+
.map(|part| as_str_opt(part).unwrap_or_default())
|
|
883
|
+
.collect(),
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
def
|
|
888
|
+
}
|