@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,1001 @@
|
|
|
1
|
+
// VENDORED: @voxgig/omni sdk-20260907-0029-0 (rust/src/runner.rs)
|
|
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.
|
|
5
|
+
//!
|
|
6
|
+
//! Port of the canonical TypeScript implementation
|
|
7
|
+
//! (typescript/src/Runner.ts). Behaviour must match, case for case.
|
|
8
|
+
//!
|
|
9
|
+
//! Rust has no exceptions, so a failing check is returned as an
|
|
10
|
+
//! [`OmniError`] rather than thrown, and a subject reports failure as
|
|
11
|
+
//! `Err(String)`.
|
|
12
|
+
|
|
13
|
+
use std::collections::BTreeMap;
|
|
14
|
+
use std::fmt;
|
|
15
|
+
use std::rc::Rc;
|
|
16
|
+
|
|
17
|
+
use super::json::{self, Json};
|
|
18
|
+
use super::regex::Regex;
|
|
19
|
+
use super::util::{
|
|
20
|
+
deepequal, getpath, jsonstr, numstr, pathify, stringify, EXISTSMARK, NULLMARK, UNDEFMARK,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/// The function under test. A spec entry's arguments arrive as a slice of
|
|
24
|
+
/// JSON values; an error is reported as its message.
|
|
25
|
+
pub type Subject = Rc<dyn Fn(&[Json]) -> Result<Json, String>>;
|
|
26
|
+
|
|
27
|
+
/// A subject that may MUTATE its arguments, which `match.args` can then
|
|
28
|
+
/// assert on. `minor/setpath` is the case in point: eight of its nine entries
|
|
29
|
+
/// assert that the store was rewritten in place.
|
|
30
|
+
///
|
|
31
|
+
/// Separate from `Subject` rather than replacing it, because omni's Rust API
|
|
32
|
+
/// has consumers outside this repository (voxgig/sekreto vendors it) and a
|
|
33
|
+
/// signature change would break them for a capability most subjects do not
|
|
34
|
+
/// need. A port that only reads its arguments keeps using `Subject`.
|
|
35
|
+
///
|
|
36
|
+
/// Dynamic-language ports have no equivalent: their shims write the mutation
|
|
37
|
+
/// back into omni's own object after the call, because the value is shared.
|
|
38
|
+
/// A Rust consumer holds a converted COPY and cannot.
|
|
39
|
+
pub type SubjectArgs = Rc<dyn Fn(&mut [Json]) -> Result<Json, String>>;
|
|
40
|
+
|
|
41
|
+
/// Run-time options for a set of test entries.
|
|
42
|
+
#[derive(Clone, Debug)]
|
|
43
|
+
pub struct Flags {
|
|
44
|
+
/// Convert JSON nulls to the NULLMARK sentinel (default: true).
|
|
45
|
+
pub null: bool,
|
|
46
|
+
/// Label used in failure messages (default: the runner name).
|
|
47
|
+
pub name: Option<String>,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
impl Default for Flags {
|
|
51
|
+
fn default() -> Flags {
|
|
52
|
+
Flags {
|
|
53
|
+
null: true,
|
|
54
|
+
name: None,
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
impl Flags {
|
|
60
|
+
/// Flags with null conversion disabled.
|
|
61
|
+
pub fn nonull() -> Flags {
|
|
62
|
+
Flags {
|
|
63
|
+
null: false,
|
|
64
|
+
name: None,
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// The host of the system under test. Every hook is optional.
|
|
70
|
+
#[derive(Clone, Default)]
|
|
71
|
+
pub struct Provider {
|
|
72
|
+
/// Resolve a test subject by name.
|
|
73
|
+
pub subject: Option<Rc<dyn Fn(&str) -> Option<Subject>>>,
|
|
74
|
+
/// Build a sub-provider from a DEF.client entry's options.
|
|
75
|
+
pub client: Option<Rc<dyn Fn(&Json) -> Provider>>,
|
|
76
|
+
/// Wrap a map argument as a call context.
|
|
77
|
+
pub contextify: Option<Rc<dyn Fn(Json) -> Json>>,
|
|
78
|
+
/// Resolve references in client options against the store.
|
|
79
|
+
pub inject: Option<Rc<dyn Fn(&Json, &Json) -> Json>>,
|
|
80
|
+
/// Build the `match.err` base from the failure, REPLACING `errify`.
|
|
81
|
+
///
|
|
82
|
+
/// Rust reports a subject failure as its message and nothing else -
|
|
83
|
+
/// `Subject` is `Fn(&[Json]) -> Result<Json, String>` - so a library
|
|
84
|
+
/// whose errors carry a code has no other way to put it in the base.
|
|
85
|
+
/// The hook receives that message and returns the base, letting a
|
|
86
|
+
/// spec assert `match: {err: {code: "x"}}` instead of pattern-matching
|
|
87
|
+
/// prose.
|
|
88
|
+
///
|
|
89
|
+
/// Adding a field to this struct is source-breaking only for a
|
|
90
|
+
/// consumer whose `Provider { .. }` literal is exhaustive; the
|
|
91
|
+
/// in-repo idiom, and the one to recommend, is `..Provider::default()`.
|
|
92
|
+
pub errify: Option<Rc<dyn Fn(&str) -> Json>>,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/// The newest spec format version this runner understands. A spec with no
|
|
96
|
+
/// OMNI block is version 0: the original, lenient format, frozen forever.
|
|
97
|
+
/// Version 1 turns on strict entry validation (see checkentry).
|
|
98
|
+
pub const SPECVERSION: f64 = 1.0;
|
|
99
|
+
|
|
100
|
+
/// Capability strings this runner supports beyond the version baseline. A
|
|
101
|
+
/// spec's OMNI.requires list is checked against this: an unknown
|
|
102
|
+
/// capability refuses the spec loudly at load time, instead of a lagging
|
|
103
|
+
/// port silently mis-running it. (Empty today; future format features
|
|
104
|
+
/// mint a string here.)
|
|
105
|
+
pub const CAPABILITIES: &[&str] = &[];
|
|
106
|
+
|
|
107
|
+
/// The complete set of fields an entry may carry. Under version 1 anything
|
|
108
|
+
/// else is an error: an unrecognised key is almost always a typo'd
|
|
109
|
+
/// assertion, and a typo'd assertion is a test that silently stopped
|
|
110
|
+
/// testing.
|
|
111
|
+
const ENTRYFIELDS: &[&str] = &["in", "args", "ctx", "out", "err", "match", "client", "id", "doc"];
|
|
112
|
+
|
|
113
|
+
/// A test failure (or a malformed spec). Distinct from an error returned
|
|
114
|
+
/// by the subject under test, which is a candidate for an `err`
|
|
115
|
+
/// expectation.
|
|
116
|
+
#[derive(Clone, Debug)]
|
|
117
|
+
pub struct OmniError {
|
|
118
|
+
pub message: String,
|
|
119
|
+
pub entry: Option<Json>,
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
impl OmniError {
|
|
123
|
+
pub fn new(message: String) -> OmniError {
|
|
124
|
+
OmniError {
|
|
125
|
+
message,
|
|
126
|
+
entry: None,
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
impl fmt::Display for OmniError {
|
|
132
|
+
fn fmt(&self, out: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
133
|
+
write!(out, "{}", self.message)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
impl std::error::Error for OmniError {}
|
|
138
|
+
|
|
139
|
+
/// Where a spec comes from: a file path, or an in-memory value.
|
|
140
|
+
pub enum SpecRef {
|
|
141
|
+
Path(String),
|
|
142
|
+
Value(Json),
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
impl From<&str> for SpecRef {
|
|
146
|
+
fn from(path: &str) -> SpecRef {
|
|
147
|
+
SpecRef::Path(path.to_string())
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
impl From<String> for SpecRef {
|
|
152
|
+
fn from(path: String) -> SpecRef {
|
|
153
|
+
SpecRef::Path(path)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
impl From<Json> for SpecRef {
|
|
158
|
+
fn from(val: Json) -> SpecRef {
|
|
159
|
+
SpecRef::Value(val)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/// Load a spec: a path to a JSON file, or an already-parsed value.
|
|
164
|
+
pub fn loadspec(specref: SpecRef) -> Result<Json, OmniError> {
|
|
165
|
+
match specref {
|
|
166
|
+
SpecRef::Value(val) => Ok(val),
|
|
167
|
+
SpecRef::Path(path) => {
|
|
168
|
+
let text = std::fs::read_to_string(&path)
|
|
169
|
+
.map_err(|_| OmniError::new(format!("omni: cannot read spec: {}", path)))?;
|
|
170
|
+
json::parse(&text)
|
|
171
|
+
.map_err(|err| OmniError::new(format!("omni: cannot parse spec: {}: {}", path, err)))
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/// Read the spec's format version from its optional top-level OMNI block,
|
|
177
|
+
/// and refuse a spec this runner cannot faithfully run: a version newer
|
|
178
|
+
/// than SPECVERSION, or a required capability not in CAPABILITIES.
|
|
179
|
+
fn resolveversion(alltests: &Json) -> Result<f64, OmniError> {
|
|
180
|
+
let meta = alltests.get("OMNI");
|
|
181
|
+
|
|
182
|
+
if meta.isabsent() {
|
|
183
|
+
return Ok(0.0);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
let versionnum = meta.get("version").asnum();
|
|
187
|
+
let isinteger = versionnum.map(|num| num == num.trunc()).unwrap_or(false);
|
|
188
|
+
if !meta.ismap() || !isinteger {
|
|
189
|
+
return Err(OmniError::new(
|
|
190
|
+
"omni: malformed OMNI version block".to_string(),
|
|
191
|
+
));
|
|
192
|
+
}
|
|
193
|
+
let version = versionnum.unwrap();
|
|
194
|
+
|
|
195
|
+
if version < 0.0 || SPECVERSION < version {
|
|
196
|
+
return Err(OmniError::new(format!(
|
|
197
|
+
"omni: unsupported spec version: {}",
|
|
198
|
+
numstr(version)
|
|
199
|
+
)));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
let requires = meta.get("requires");
|
|
203
|
+
if !requires.isabsent() {
|
|
204
|
+
let list = match requires.aslist() {
|
|
205
|
+
Some(list) => list,
|
|
206
|
+
None => {
|
|
207
|
+
return Err(OmniError::new(
|
|
208
|
+
"omni: malformed OMNI requires list".to_string(),
|
|
209
|
+
))
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
for cap in list {
|
|
214
|
+
let capstr = cap.asstr();
|
|
215
|
+
if capstr.is_none() || !CAPABILITIES.contains(&capstr.unwrap()) {
|
|
216
|
+
return Err(OmniError::new(format!(
|
|
217
|
+
"omni: spec requires unsupported capability: {}",
|
|
218
|
+
stringify(cap)
|
|
219
|
+
)));
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
Ok(version)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/// Strict entry validation, applied when the spec declares version 1 or
|
|
228
|
+
/// later. The lenient format converts each of these mistakes into a
|
|
229
|
+
/// silent pass or a dead field; here they fail with the entry named.
|
|
230
|
+
fn checkentry(flags: &Flags, index: usize, entry: &Json) -> Result<(), OmniError> {
|
|
231
|
+
let map = match entry.asmap() {
|
|
232
|
+
Some(map) => map,
|
|
233
|
+
None => return Err(fail(flags, index, entry, "entry is not a map", None, None)),
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
for key in map.keys() {
|
|
237
|
+
if !ENTRYFIELDS.contains(&key.as_str()) {
|
|
238
|
+
return Err(fail(
|
|
239
|
+
flags,
|
|
240
|
+
index,
|
|
241
|
+
entry,
|
|
242
|
+
&format!("unknown entry field: {}", key),
|
|
243
|
+
None,
|
|
244
|
+
None,
|
|
245
|
+
));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
let mut argsources = 0;
|
|
250
|
+
for key in ["in", "args", "ctx"] {
|
|
251
|
+
if entry.has(key) {
|
|
252
|
+
argsources += 1;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
if 1 < argsources {
|
|
256
|
+
return Err(fail(
|
|
257
|
+
flags,
|
|
258
|
+
index,
|
|
259
|
+
entry,
|
|
260
|
+
"entry has more than one of in, args, ctx",
|
|
261
|
+
None,
|
|
262
|
+
None,
|
|
263
|
+
));
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if !entry.get("err").isnone() && !entry.get("out").isabsent() {
|
|
267
|
+
return Err(fail(
|
|
268
|
+
flags,
|
|
269
|
+
index,
|
|
270
|
+
entry,
|
|
271
|
+
"entry has both err and out",
|
|
272
|
+
None,
|
|
273
|
+
None,
|
|
274
|
+
));
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
let id = entry.get("id");
|
|
278
|
+
if !id.isabsent() && id.asstr().is_none() {
|
|
279
|
+
return Err(fail(
|
|
280
|
+
flags,
|
|
281
|
+
index,
|
|
282
|
+
entry,
|
|
283
|
+
"entry id is not a string",
|
|
284
|
+
None,
|
|
285
|
+
None,
|
|
286
|
+
));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
Ok(())
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/// Validate a version-1 group up front, against the AUTHORED entries -
|
|
293
|
+
/// null-normalisation would otherwise rewrite an authored null (e.g.
|
|
294
|
+
/// id: null) into a sentinel string and hide it from validation. A
|
|
295
|
+
/// malformed spec is a spec error, not a test result, so it fails before
|
|
296
|
+
/// any subject runs.
|
|
297
|
+
fn checkset(flags: &Flags, testspec: &Json, normalset: &[Json]) -> Result<(), OmniError> {
|
|
298
|
+
let origset: Vec<Json> = match testspec.get("set") {
|
|
299
|
+
Json::List(list) => list,
|
|
300
|
+
_ => normalset.to_vec(),
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
let label = flags.name.clone().unwrap_or_else(|| "set".to_string());
|
|
304
|
+
|
|
305
|
+
if origset.is_empty() && !matches!(testspec.get("empty"), Json::Bool(true)) {
|
|
306
|
+
return Err(OmniError::new(format!("omni: empty test set: {}", label)));
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
for (index, entry) in origset.iter().enumerate() {
|
|
310
|
+
checkentry(flags, index, entry)?;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
Ok(())
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/// Find `primary.<name>`, then `<name>`, then the whole spec.
|
|
317
|
+
pub fn resolvespec(name: &str, alltests: &Json) -> Json {
|
|
318
|
+
if name.is_empty() {
|
|
319
|
+
return alltests.clone();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
let primary = alltests.get("primary");
|
|
323
|
+
let section = primary.get(name);
|
|
324
|
+
if !section.isabsent() {
|
|
325
|
+
return section;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
let section = alltests.get(name);
|
|
329
|
+
if !section.isabsent() {
|
|
330
|
+
return section;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
alltests.clone()
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/// What a runner returns for one named spec section.
|
|
337
|
+
pub struct RunPack {
|
|
338
|
+
pub spec: Json,
|
|
339
|
+
pub subject: Option<Subject>,
|
|
340
|
+
pub client: Provider,
|
|
341
|
+
name: String,
|
|
342
|
+
provider: Provider,
|
|
343
|
+
clients: BTreeMap<String, Provider>,
|
|
344
|
+
specversion: f64,
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
impl RunPack {
|
|
348
|
+
/// A named group of the resolved spec.
|
|
349
|
+
pub fn set(&self, name: &str) -> Json {
|
|
350
|
+
self.spec.get(name)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/// Run one set of test entries.
|
|
354
|
+
pub fn runset(&self, testspec: &Json, subject: Option<&Subject>) -> Result<(), OmniError> {
|
|
355
|
+
self.runsetflags(testspec, &Flags::default(), subject)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/// Run one set of test entries with flags.
|
|
359
|
+
pub fn runsetflags(
|
|
360
|
+
&self,
|
|
361
|
+
testspec: &Json,
|
|
362
|
+
flags: &Flags,
|
|
363
|
+
subject: Option<&Subject>,
|
|
364
|
+
) -> Result<(), OmniError> {
|
|
365
|
+
self.drive(testspec, flags, subject, None)
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/// Run one set of test entries whose subject may mutate its arguments.
|
|
369
|
+
/// Everything else is identical to `runsetflags`.
|
|
370
|
+
pub fn runsetflags_args(
|
|
371
|
+
&self,
|
|
372
|
+
testspec: &Json,
|
|
373
|
+
flags: &Flags,
|
|
374
|
+
subject: &SubjectArgs,
|
|
375
|
+
) -> Result<(), OmniError> {
|
|
376
|
+
self.drive(testspec, flags, None, Some(subject))
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
fn drive(
|
|
380
|
+
&self,
|
|
381
|
+
testspec: &Json,
|
|
382
|
+
flags: &Flags,
|
|
383
|
+
subject: Option<&Subject>,
|
|
384
|
+
argsubject: Option<&SubjectArgs>,
|
|
385
|
+
) -> Result<(), OmniError> {
|
|
386
|
+
let mut useflags = flags.clone();
|
|
387
|
+
if useflags.name.is_none() {
|
|
388
|
+
useflags.name = Some(if self.name.is_empty() {
|
|
389
|
+
"set".to_string()
|
|
390
|
+
} else {
|
|
391
|
+
self.name.clone()
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
let label = useflags.name.clone().unwrap_or_else(|| "set".to_string());
|
|
396
|
+
|
|
397
|
+
// The client path always resolves an ordinary Subject; an args-taking
|
|
398
|
+
// subject is used only for entries that name no client, which is
|
|
399
|
+
// every entry the corpus asserts `match.args` on.
|
|
400
|
+
let fallback: Subject = Rc::new(|_args: &[Json]| {
|
|
401
|
+
Err("omni: no test subject".to_string())
|
|
402
|
+
});
|
|
403
|
+
let usesubject = match subject.cloned().or_else(|| self.subject.clone()) {
|
|
404
|
+
Some(found) => found,
|
|
405
|
+
None if argsubject.is_some() => fallback,
|
|
406
|
+
None => {
|
|
407
|
+
return Err(OmniError::new(format!(
|
|
408
|
+
"omni: no test subject for: {}",
|
|
409
|
+
label
|
|
410
|
+
)))
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
let testspecmap = fixjson(testspec, &useflags);
|
|
415
|
+
let testset = match testspecmap.get("set") {
|
|
416
|
+
Json::List(list) => list,
|
|
417
|
+
_ => {
|
|
418
|
+
return Err(OmniError::new(format!(
|
|
419
|
+
"omni: test spec has no set: {}",
|
|
420
|
+
label
|
|
421
|
+
)))
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
if 1.0 <= self.specversion {
|
|
426
|
+
checkset(&useflags, testspec, &testset)?;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
for (index, rawentry) in testset.iter().enumerate() {
|
|
430
|
+
let mut entry = resolveentry(rawentry.clone(), &useflags);
|
|
431
|
+
|
|
432
|
+
let (client, entrysubject) = self.resolvetestpack(&entry, &usesubject)?;
|
|
433
|
+
let mut args = self.resolveargs(&mut entry, &client);
|
|
434
|
+
|
|
435
|
+
let called = match argsubject {
|
|
436
|
+
Some(mutable) if entry.get("client").asstr().is_none() => mutable(&mut args),
|
|
437
|
+
_ => entrysubject(&args),
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
match called {
|
|
441
|
+
Err(message) => {
|
|
442
|
+
handleerror(&useflags, index, &entry, &message, &self.provider)?;
|
|
443
|
+
}
|
|
444
|
+
Ok(rawres) => {
|
|
445
|
+
let res = fixjson(&rawres, &useflags);
|
|
446
|
+
jset(&mut entry, "res", res.clone());
|
|
447
|
+
checkresult(&useflags, index, &entry, &args, &res)?;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
Ok(())
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
fn resolvetestpack(
|
|
456
|
+
&self,
|
|
457
|
+
entry: &Json,
|
|
458
|
+
subject: &Subject,
|
|
459
|
+
) -> Result<(Provider, Subject), OmniError> {
|
|
460
|
+
let clientname = entry.get("client");
|
|
461
|
+
|
|
462
|
+
let name = match clientname.asstr() {
|
|
463
|
+
Some(text) => text,
|
|
464
|
+
None => return Ok((self.provider.clone(), subject.clone())),
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
let client = self.clients.get(name).ok_or_else(|| OmniError {
|
|
468
|
+
message: format!("omni: unknown client: {}", name),
|
|
469
|
+
entry: Some(entry.clone()),
|
|
470
|
+
})?;
|
|
471
|
+
|
|
472
|
+
let clientsubject = resolvesubject(&self.name, client).unwrap_or_else(|| subject.clone());
|
|
473
|
+
|
|
474
|
+
Ok((client.clone(), clientsubject))
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/// Build the argument list: `ctx`, `args`, or `in`.
|
|
478
|
+
fn resolveargs(&self, entry: &mut Json, _client: &Provider) -> Vec<Json> {
|
|
479
|
+
let hasctx = entry.has("ctx");
|
|
480
|
+
let hasargs = entry.has("args");
|
|
481
|
+
|
|
482
|
+
let mut args: Vec<Json> = if hasctx {
|
|
483
|
+
vec![entry.get("ctx")]
|
|
484
|
+
} else if hasargs {
|
|
485
|
+
match entry.get("args") {
|
|
486
|
+
Json::List(list) => list,
|
|
487
|
+
other => vec![other],
|
|
488
|
+
}
|
|
489
|
+
} else {
|
|
490
|
+
vec![entry.get("in")]
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
if (hasctx || hasargs) && !args.is_empty() && args[0].ismap() {
|
|
494
|
+
let mut first = args[0].clone();
|
|
495
|
+
if let Some(contextify) = &self.provider.contextify {
|
|
496
|
+
first = contextify(first);
|
|
497
|
+
}
|
|
498
|
+
// The resolved client is a live Provider (closures over the
|
|
499
|
+
// system under test), and this port's Json carries no
|
|
500
|
+
// host-object variant to hold one - so canonical's
|
|
501
|
+
// `first.client = testpack.client` becomes presence, not
|
|
502
|
+
// identity: enough for a subject to prove the runner attached
|
|
503
|
+
// a client at all.
|
|
504
|
+
if let Json::Map(map) = &mut first {
|
|
505
|
+
map.insert("client".to_string(), Json::Bool(true));
|
|
506
|
+
}
|
|
507
|
+
args[0] = first.clone();
|
|
508
|
+
jset(entry, "ctx", first);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
args
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
fn resolvesubject(name: &str, provider: &Provider) -> Option<Subject> {
|
|
516
|
+
if name.is_empty() {
|
|
517
|
+
return None;
|
|
518
|
+
}
|
|
519
|
+
provider.subject.as_ref().and_then(|resolve| resolve(name))
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/// An entry with no `out` expects a null (or absent) result.
|
|
523
|
+
fn resolveentry(entry: Json, flags: &Flags) -> Json {
|
|
524
|
+
let mut out = entry;
|
|
525
|
+
if out.get("out").isnone() && flags.null {
|
|
526
|
+
jset(&mut out, "out", Json::str(NULLMARK));
|
|
527
|
+
}
|
|
528
|
+
out
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
/// Set a map entry (no-op for non-maps).
|
|
532
|
+
fn jset(val: &mut Json, key: &str, entry: Json) {
|
|
533
|
+
if let Json::Map(map) = val {
|
|
534
|
+
map.insert(key.to_string(), entry);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/// Nulls (and absent values) become NULLMARK. Always a fresh copy.
|
|
539
|
+
pub fn fixjson(val: &Json, flags: &Flags) -> Json {
|
|
540
|
+
fixjsonval(val, flags.null)
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
fn fixjsonval(val: &Json, donull: bool) -> Json {
|
|
544
|
+
match val {
|
|
545
|
+
// Canonical returns the value UNCHANGED when donull is false
|
|
546
|
+
// (typescript/src/Runner.ts): `undefined` stays undefined and `null`
|
|
547
|
+
// stays null. Answering Json::Null for both collapsed two states the
|
|
548
|
+
// corpus distinguishes - an absent result became indistinguishable
|
|
549
|
+
// from a null one, so a subject that returned nothing could never
|
|
550
|
+
// match an entry with no `out`.
|
|
551
|
+
//
|
|
552
|
+
// Same defect omni-lua carried (voxgig/omni#17). Only ports whose
|
|
553
|
+
// model has a SEPARATE absent value can express it; the rest have
|
|
554
|
+
// nothing to lose here.
|
|
555
|
+
Json::Absent | Json::Null => {
|
|
556
|
+
if donull {
|
|
557
|
+
Json::str(NULLMARK)
|
|
558
|
+
} else {
|
|
559
|
+
val.clone()
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
Json::List(list) => Json::List(list.iter().map(|e| fixjsonval(e, donull)).collect()),
|
|
563
|
+
Json::Map(map) => {
|
|
564
|
+
let mut out = BTreeMap::new();
|
|
565
|
+
for (key, entry) in map.iter() {
|
|
566
|
+
out.insert(key.clone(), fixjsonval(entry, donull));
|
|
567
|
+
}
|
|
568
|
+
Json::Map(out)
|
|
569
|
+
}
|
|
570
|
+
other => other.clone(),
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/// The JSON form of an error: always at least {name,message}.
|
|
575
|
+
pub fn errify(message: &str) -> Json {
|
|
576
|
+
Json::map(vec![
|
|
577
|
+
("name", Json::str("Error")),
|
|
578
|
+
("message", Json::str(message)),
|
|
579
|
+
])
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/// The label of one entry, for failure messages.
|
|
583
|
+
fn entryref(flags: &Flags, index: usize, entry: &Json) -> String {
|
|
584
|
+
let label = flags.name.clone().unwrap_or_else(|| "set".to_string());
|
|
585
|
+
let id = entry.get("id");
|
|
586
|
+
let idpart = if id.isabsent() {
|
|
587
|
+
String::new()
|
|
588
|
+
} else {
|
|
589
|
+
format!(" ({})", stringify(&id))
|
|
590
|
+
};
|
|
591
|
+
format!("{}[{}]{}", label, index, idpart)
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
fn fail(
|
|
595
|
+
flags: &Flags,
|
|
596
|
+
index: usize,
|
|
597
|
+
entry: &Json,
|
|
598
|
+
reason: &str,
|
|
599
|
+
expected: Option<String>,
|
|
600
|
+
actual: Option<String>,
|
|
601
|
+
) -> OmniError {
|
|
602
|
+
let mut message = format!("omni: {}: {}", entryref(flags, index, entry), reason);
|
|
603
|
+
if let Some(text) = expected {
|
|
604
|
+
message.push_str(&format!("\n expected: {}", text));
|
|
605
|
+
}
|
|
606
|
+
if let Some(text) = actual {
|
|
607
|
+
message.push_str(&format!("\n actual: {}", text));
|
|
608
|
+
}
|
|
609
|
+
message.push_str(&format!("\n entry: {}", jsonstr(&entrysummary(entry))));
|
|
610
|
+
|
|
611
|
+
OmniError {
|
|
612
|
+
message,
|
|
613
|
+
entry: Some(entry.clone()),
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
/// The spec-defined part of an entry (drop runner bookkeeping).
|
|
618
|
+
fn entrysummary(entry: &Json) -> Json {
|
|
619
|
+
match entry {
|
|
620
|
+
Json::Map(map) => {
|
|
621
|
+
let mut out = BTreeMap::new();
|
|
622
|
+
for (key, val) in map.iter() {
|
|
623
|
+
if "res" != key && "thrown" != key && "ctx" != key {
|
|
624
|
+
out.insert(key.clone(), val.clone());
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
Json::Map(out)
|
|
628
|
+
}
|
|
629
|
+
other => other.clone(),
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
fn checkresult(
|
|
634
|
+
flags: &Flags,
|
|
635
|
+
index: usize,
|
|
636
|
+
entry: &Json,
|
|
637
|
+
args: &[Json],
|
|
638
|
+
res: &Json,
|
|
639
|
+
) -> Result<(), OmniError> {
|
|
640
|
+
let mut matched = false;
|
|
641
|
+
|
|
642
|
+
let entryerr = entry.get("err");
|
|
643
|
+
if !entryerr.isnone() {
|
|
644
|
+
return Err(fail(
|
|
645
|
+
flags,
|
|
646
|
+
index,
|
|
647
|
+
entry,
|
|
648
|
+
"expected error did not occur",
|
|
649
|
+
Some(stringify(&entryerr)),
|
|
650
|
+
Some(stringify(res)),
|
|
651
|
+
));
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
let check = entry.get("match");
|
|
655
|
+
if !check.isnone() {
|
|
656
|
+
let base = Json::map(vec![
|
|
657
|
+
("in", entry.get("in")),
|
|
658
|
+
("args", Json::List(args.to_vec())),
|
|
659
|
+
("out", entry.get("res")),
|
|
660
|
+
("ctx", entry.get("ctx")),
|
|
661
|
+
]);
|
|
662
|
+
matchcheck(flags, index, entry, &check, &base)?;
|
|
663
|
+
matched = true;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
let out = entry.get("out");
|
|
667
|
+
|
|
668
|
+
if deepequal(res, &out) {
|
|
669
|
+
return Ok(());
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
// NOTE: a match with no explicit out is a complete check on its own.
|
|
673
|
+
if matched && (out.isnone() || Some(NULLMARK) == out.asstr()) {
|
|
674
|
+
return Ok(());
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
Err(fail(
|
|
678
|
+
flags,
|
|
679
|
+
index,
|
|
680
|
+
entry,
|
|
681
|
+
"result mismatch",
|
|
682
|
+
Some(stringify(&out)),
|
|
683
|
+
Some(stringify(res)),
|
|
684
|
+
))
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/// The error base a `match.err` sees: the provider's own, when it has one.
|
|
688
|
+
fn errbase(message: &str, provider: &Provider) -> Json {
|
|
689
|
+
match &provider.errify {
|
|
690
|
+
Some(hook) => hook(message),
|
|
691
|
+
None => errify(message),
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
fn handleerror(
|
|
696
|
+
flags: &Flags,
|
|
697
|
+
index: usize,
|
|
698
|
+
entry: &Json,
|
|
699
|
+
message: &str,
|
|
700
|
+
provider: &Provider,
|
|
701
|
+
) -> Result<(), OmniError> {
|
|
702
|
+
let entryerr = entry.get("err");
|
|
703
|
+
|
|
704
|
+
if !entryerr.isnone() {
|
|
705
|
+
let istrue = matches!(entryerr, Json::Bool(true));
|
|
706
|
+
|
|
707
|
+
if istrue || matchval(&entryerr, &Json::str(message)) {
|
|
708
|
+
let check = entry.get("match");
|
|
709
|
+
if !check.isnone() {
|
|
710
|
+
let base = Json::map(vec![
|
|
711
|
+
("in", entry.get("in")),
|
|
712
|
+
("out", entry.get("res")),
|
|
713
|
+
("ctx", entry.get("ctx")),
|
|
714
|
+
("err", errbase(message, provider)),
|
|
715
|
+
]);
|
|
716
|
+
matchcheck(flags, index, entry, &check, &base)?;
|
|
717
|
+
}
|
|
718
|
+
return Ok(());
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
return Err(fail(
|
|
722
|
+
flags,
|
|
723
|
+
index,
|
|
724
|
+
entry,
|
|
725
|
+
"error mismatch",
|
|
726
|
+
Some(stringify(&entryerr)),
|
|
727
|
+
Some(message.to_string()),
|
|
728
|
+
));
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
Err(fail(
|
|
732
|
+
flags,
|
|
733
|
+
index,
|
|
734
|
+
entry,
|
|
735
|
+
"unexpected error",
|
|
736
|
+
None,
|
|
737
|
+
Some(message.to_string()),
|
|
738
|
+
))
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/// Check that every leaf of `check` is present, and matches, in `base`.
|
|
742
|
+
pub fn matchcheck(
|
|
743
|
+
flags: &Flags,
|
|
744
|
+
index: usize,
|
|
745
|
+
entry: &Json,
|
|
746
|
+
check: &Json,
|
|
747
|
+
base: &Json,
|
|
748
|
+
) -> Result<(), OmniError> {
|
|
749
|
+
matchwalk(flags, index, entry, check, base, &mut Vec::new())
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
fn matchwalk(
|
|
753
|
+
flags: &Flags,
|
|
754
|
+
index: usize,
|
|
755
|
+
entry: &Json,
|
|
756
|
+
check: &Json,
|
|
757
|
+
base: &Json,
|
|
758
|
+
path: &mut Vec<String>,
|
|
759
|
+
) -> Result<(), OmniError> {
|
|
760
|
+
let where_ = |path: &[String]| {
|
|
761
|
+
if path.is_empty() {
|
|
762
|
+
"<root>".to_string()
|
|
763
|
+
} else {
|
|
764
|
+
pathify(path)
|
|
765
|
+
}
|
|
766
|
+
};
|
|
767
|
+
|
|
768
|
+
match check {
|
|
769
|
+
Json::List(list) => {
|
|
770
|
+
for (subindex, subcheck) in list.iter().enumerate() {
|
|
771
|
+
path.push(subindex.to_string());
|
|
772
|
+
matchwalk(flags, index, entry, subcheck, base, path)?;
|
|
773
|
+
path.pop();
|
|
774
|
+
}
|
|
775
|
+
Ok(())
|
|
776
|
+
}
|
|
777
|
+
Json::Map(map) => {
|
|
778
|
+
for (key, subcheck) in map.iter() {
|
|
779
|
+
path.push(key.clone());
|
|
780
|
+
matchwalk(flags, index, entry, subcheck, base, path)?;
|
|
781
|
+
path.pop();
|
|
782
|
+
}
|
|
783
|
+
Ok(())
|
|
784
|
+
}
|
|
785
|
+
leaf => {
|
|
786
|
+
let baseval = getpath(base, path);
|
|
787
|
+
|
|
788
|
+
// The sentinels are tested BEFORE the identity check below.
|
|
789
|
+
// Otherwise a subject returning the literal string "__UNDEF__"
|
|
790
|
+
// satisfies an assertion that the key is absent - two mutually
|
|
791
|
+
// exclusive states passing one check. A sentinel that accepts
|
|
792
|
+
// its own literal is not a sentinel. (NULLMARK still accepts
|
|
793
|
+
// NULLMARK: under the default null flag a real null has already
|
|
794
|
+
// been normalised to it, so the two are genuinely
|
|
795
|
+
// indistinguishable here - that one needs a raw-value escape,
|
|
796
|
+
// not an ordering change.)
|
|
797
|
+
|
|
798
|
+
// Explicitly absent: satisfied only by a genuinely missing key,
|
|
799
|
+
// never by a present null (the distinction the sentinels exist
|
|
800
|
+
// to keep).
|
|
801
|
+
if Some(UNDEFMARK) == leaf.asstr() {
|
|
802
|
+
if baseval.isabsent() {
|
|
803
|
+
return Ok(());
|
|
804
|
+
}
|
|
805
|
+
return Err(fail(
|
|
806
|
+
flags,
|
|
807
|
+
index,
|
|
808
|
+
entry,
|
|
809
|
+
&format!("expected absent at {}", where_(path)),
|
|
810
|
+
Some("absent".to_string()),
|
|
811
|
+
Some(stringify(&baseval)),
|
|
812
|
+
));
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
// Explicitly null: satisfied only by a present null.
|
|
816
|
+
if Some(NULLMARK) == leaf.asstr() {
|
|
817
|
+
if baseval.isnull() || Some(NULLMARK) == baseval.asstr() {
|
|
818
|
+
return Ok(());
|
|
819
|
+
}
|
|
820
|
+
return Err(fail(
|
|
821
|
+
flags,
|
|
822
|
+
index,
|
|
823
|
+
entry,
|
|
824
|
+
&format!("expected null at {}", where_(path)),
|
|
825
|
+
Some("null".to_string()),
|
|
826
|
+
Some(stringify(&baseval)),
|
|
827
|
+
));
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
// Explicitly present: any present value, including null.
|
|
831
|
+
if Some(EXISTSMARK) == leaf.asstr() {
|
|
832
|
+
if !baseval.isabsent() {
|
|
833
|
+
return Ok(());
|
|
834
|
+
}
|
|
835
|
+
return Err(fail(
|
|
836
|
+
flags,
|
|
837
|
+
index,
|
|
838
|
+
entry,
|
|
839
|
+
&format!("expected present at {}", where_(path)),
|
|
840
|
+
Some("present".to_string()),
|
|
841
|
+
Some("absent".to_string()),
|
|
842
|
+
));
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// Identical values match. This sits below the sentinel branches
|
|
846
|
+
// on purpose - see the note above.
|
|
847
|
+
if deepequal(leaf, &baseval) {
|
|
848
|
+
return Ok(());
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
// A concrete expectation never matches a missing key - a match
|
|
852
|
+
// leaf against an absent value must fail, not substring-match
|
|
853
|
+
// "undefined".
|
|
854
|
+
if baseval.isabsent() {
|
|
855
|
+
return Err(fail(
|
|
856
|
+
flags,
|
|
857
|
+
index,
|
|
858
|
+
entry,
|
|
859
|
+
&format!("match failed at {}", where_(path)),
|
|
860
|
+
Some(stringify(leaf)),
|
|
861
|
+
Some("absent".to_string()),
|
|
862
|
+
));
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
if matchval(leaf, &baseval) {
|
|
866
|
+
return Ok(());
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
Err(fail(
|
|
870
|
+
flags,
|
|
871
|
+
index,
|
|
872
|
+
entry,
|
|
873
|
+
&format!("match failed at {}", where_(path)),
|
|
874
|
+
Some(stringify(leaf)),
|
|
875
|
+
Some(stringify(&baseval)),
|
|
876
|
+
))
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
/// Match one leaf: /regex/ or case-insensitive substring for strings.
|
|
882
|
+
pub fn matchval(check: &Json, base: &Json) -> bool {
|
|
883
|
+
if deepequal(check, base) {
|
|
884
|
+
return true;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
let want = check.clone();
|
|
888
|
+
|
|
889
|
+
if want.isnone() {
|
|
890
|
+
return base.isnone() || Some(NULLMARK) == base.asstr();
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
if let Some(text) = want.asstr() {
|
|
894
|
+
// An empty want would substring-match anything: reject it.
|
|
895
|
+
if text.is_empty() {
|
|
896
|
+
return false;
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
let basestr = stringify(base);
|
|
900
|
+
|
|
901
|
+
if 2 < text.len() && text.starts_with('/') && text.ends_with('/') {
|
|
902
|
+
let pattern = &text[1..text.len() - 1];
|
|
903
|
+
return match Regex::new(pattern) {
|
|
904
|
+
Ok(regex) => regex.is_match(&basestr),
|
|
905
|
+
Err(_) => false,
|
|
906
|
+
};
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
return basestr.to_lowercase().contains(&text.to_lowercase());
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
deepequal(&want, base)
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
/// Convert NULLMARK sentinels back into real nulls.
|
|
916
|
+
pub fn nullmodifier(val: &Json) -> Json {
|
|
917
|
+
match val {
|
|
918
|
+
Json::Str(text) if NULLMARK == text => Json::Null,
|
|
919
|
+
Json::Str(text) => Json::Str(text.replace(NULLMARK, "null")),
|
|
920
|
+
other => other.clone(),
|
|
921
|
+
}
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
/// A loaded spec plus its provider.
|
|
925
|
+
pub struct Runner {
|
|
926
|
+
alltests: Json,
|
|
927
|
+
provider: Provider,
|
|
928
|
+
specversion: f64,
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
impl Runner {
|
|
932
|
+
/// Resolve one named section of the spec.
|
|
933
|
+
pub fn runner(&self, name: &str, store: Option<&Json>) -> Result<RunPack, OmniError> {
|
|
934
|
+
let spec = resolvespec(name, &self.alltests);
|
|
935
|
+
let clients = self.resolveclients(&spec, store)?;
|
|
936
|
+
let subject = resolvesubject(name, &self.provider);
|
|
937
|
+
|
|
938
|
+
Ok(RunPack {
|
|
939
|
+
spec,
|
|
940
|
+
subject,
|
|
941
|
+
client: self.provider.clone(),
|
|
942
|
+
name: name.to_string(),
|
|
943
|
+
provider: self.provider.clone(),
|
|
944
|
+
clients,
|
|
945
|
+
specversion: self.specversion,
|
|
946
|
+
})
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
fn resolveclients(
|
|
950
|
+
&self,
|
|
951
|
+
spec: &Json,
|
|
952
|
+
store: Option<&Json>,
|
|
953
|
+
) -> Result<BTreeMap<String, Provider>, OmniError> {
|
|
954
|
+
let mut clients = BTreeMap::new();
|
|
955
|
+
|
|
956
|
+
let defclient = spec.get("DEF").get("client");
|
|
957
|
+
let defmap = match defclient.asmap() {
|
|
958
|
+
Some(map) => map.clone(),
|
|
959
|
+
None => return Ok(clients),
|
|
960
|
+
};
|
|
961
|
+
|
|
962
|
+
// A spec may define clients that a given test run never references.
|
|
963
|
+
let clientmaker = match &self.provider.client {
|
|
964
|
+
Some(maker) => maker.clone(),
|
|
965
|
+
None => return Ok(clients),
|
|
966
|
+
};
|
|
967
|
+
|
|
968
|
+
for (clientname, cdef) in defmap.iter() {
|
|
969
|
+
let mut copts = cdef.get("test").get("options");
|
|
970
|
+
if copts.isabsent() {
|
|
971
|
+
copts = Json::map(vec![]);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
if let (Some(inject), Some(store)) = (&self.provider.inject, store) {
|
|
975
|
+
copts = inject(&copts, store);
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
clients.insert(clientname.clone(), clientmaker(&copts));
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
Ok(clients)
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
/// Make a runner for a spec file (or spec value) and a provider. Resolves
|
|
986
|
+
/// the spec's format version immediately - fail fast, before any group
|
|
987
|
+
/// runs, rather than mid-suite.
|
|
988
|
+
pub fn make_runner<S: Into<SpecRef>>(specref: S, provider: Provider) -> Result<Runner, OmniError> {
|
|
989
|
+
let alltests = loadspec(specref.into())?;
|
|
990
|
+
let specversion = resolveversion(&alltests)?;
|
|
991
|
+
Ok(Runner {
|
|
992
|
+
alltests,
|
|
993
|
+
provider,
|
|
994
|
+
specversion,
|
|
995
|
+
})
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
/// Render a number the same way in every port (re-exported for subjects).
|
|
999
|
+
pub fn numtext(val: f64) -> String {
|
|
1000
|
+
numstr(val)
|
|
1001
|
+
}
|