@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,864 @@
|
|
|
1
|
+
// VENDORED: @voxgig/omni sdk-20260907-0029-0 (csharp/src/Runner.cs)
|
|
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 (C# port).
|
|
5
|
+
//
|
|
6
|
+
// Port of the canonical TypeScript implementation
|
|
7
|
+
// (typescript/src/Runner.ts). Behaviour must match, case for case.
|
|
8
|
+
|
|
9
|
+
using System;
|
|
10
|
+
using System.Collections.Generic;
|
|
11
|
+
using System.Globalization;
|
|
12
|
+
using System.IO;
|
|
13
|
+
using System.Linq;
|
|
14
|
+
using System.Text;
|
|
15
|
+
using System.Text.RegularExpressions;
|
|
16
|
+
|
|
17
|
+
namespace Voxgig.Omni
|
|
18
|
+
{
|
|
19
|
+
/// <summary>The function under test. Arguments arrive as JSON values.</summary>
|
|
20
|
+
public delegate object Subject(params object[] args);
|
|
21
|
+
|
|
22
|
+
/// <summary>A test failure (or a malformed spec).</summary>
|
|
23
|
+
public class OmniError : Exception
|
|
24
|
+
{
|
|
25
|
+
public object Entry { get; }
|
|
26
|
+
|
|
27
|
+
public OmniError(string message) : this(message, null) { }
|
|
28
|
+
|
|
29
|
+
public OmniError(string message, object entry) : base(message)
|
|
30
|
+
{
|
|
31
|
+
Entry = entry;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// <summary>Run-time options for a set of test entries.</summary>
|
|
36
|
+
public class Flags
|
|
37
|
+
{
|
|
38
|
+
public bool Null { get; set; } = true;
|
|
39
|
+
public string Name { get; set; }
|
|
40
|
+
|
|
41
|
+
public static Flags NoNull() => new Flags { Null = false };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// <summary>The host of the system under test. Every hook is optional.</summary>
|
|
45
|
+
public class Provider
|
|
46
|
+
{
|
|
47
|
+
/// <summary>Resolve a test subject by name.</summary>
|
|
48
|
+
public Func<string, Subject> SubjectFor { get; set; }
|
|
49
|
+
|
|
50
|
+
/// <summary>Build a sub-provider from a DEF.client entry's options.</summary>
|
|
51
|
+
public Func<object, Provider> Client { get; set; }
|
|
52
|
+
|
|
53
|
+
/// <summary>Wrap a map argument as a call context.</summary>
|
|
54
|
+
public Func<object, object> Contextify { get; set; }
|
|
55
|
+
|
|
56
|
+
/// <summary>Resolve references in client options against the store.</summary>
|
|
57
|
+
public Func<object, object, object> Inject { get; set; }
|
|
58
|
+
|
|
59
|
+
/// <summary>
|
|
60
|
+
/// Build the <c>match.err</c> base from the raised error, REPLACING
|
|
61
|
+
/// <see cref="Runner.Errify"/>. A library whose errors carry a code
|
|
62
|
+
/// can then assert on it with <c>match: {err: {code: "x"}}</c>
|
|
63
|
+
/// instead of pattern-matching prose.
|
|
64
|
+
/// </summary>
|
|
65
|
+
public Func<object, object> Errify { get; set; }
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/// <summary>What a runner returns for one named spec section.</summary>
|
|
69
|
+
public class RunPack
|
|
70
|
+
{
|
|
71
|
+
public object Spec { get; }
|
|
72
|
+
public Subject Subject { get; }
|
|
73
|
+
public Provider Client { get; }
|
|
74
|
+
|
|
75
|
+
private readonly Provider provider;
|
|
76
|
+
private readonly Dictionary<string, Provider> clients;
|
|
77
|
+
private readonly string name;
|
|
78
|
+
private readonly int specversion;
|
|
79
|
+
|
|
80
|
+
internal RunPack(object spec, Subject subject, Provider provider,
|
|
81
|
+
Dictionary<string, Provider> clients, string name, int specversion)
|
|
82
|
+
{
|
|
83
|
+
Spec = spec;
|
|
84
|
+
Subject = subject;
|
|
85
|
+
Client = provider;
|
|
86
|
+
this.provider = provider;
|
|
87
|
+
this.clients = clients;
|
|
88
|
+
this.name = name;
|
|
89
|
+
this.specversion = specversion;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/// <summary>A named group of the resolved spec.</summary>
|
|
93
|
+
public object Set(string setname)
|
|
94
|
+
{
|
|
95
|
+
return Spec is IDictionary<string, object> map && map.ContainsKey(setname) ? map[setname] : null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/// <summary>Run one set of test entries.</summary>
|
|
99
|
+
public void RunSet(object testspec, Subject testsubject = null)
|
|
100
|
+
{
|
|
101
|
+
RunSetFlags(testspec, new Flags(), testsubject);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/// <summary>Run one set of test entries with flags.</summary>
|
|
105
|
+
public void RunSetFlags(object testspec, Flags flags, Subject testsubject = null)
|
|
106
|
+
{
|
|
107
|
+
var useflags = new Flags
|
|
108
|
+
{
|
|
109
|
+
Null = null == flags ? true : flags.Null,
|
|
110
|
+
Name = null == flags || string.IsNullOrEmpty(flags.Name)
|
|
111
|
+
? (string.IsNullOrEmpty(name) ? "set" : name)
|
|
112
|
+
: flags.Name,
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
Subject subject = testsubject ?? Subject;
|
|
116
|
+
if (null == subject)
|
|
117
|
+
{
|
|
118
|
+
throw new OmniError("omni: no test subject for: " + useflags.Name);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
var testspecmap = Runner.FixJson(testspec, useflags.Null) as IDictionary<string, object>;
|
|
122
|
+
if (null == testspecmap || !(testspecmap.ContainsKey("set") && testspecmap["set"] is IList<object>))
|
|
123
|
+
{
|
|
124
|
+
throw new OmniError("omni: test spec has no set: " + useflags.Name);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
var testset = (IList<object>)testspecmap["set"];
|
|
128
|
+
|
|
129
|
+
if (1 <= specversion)
|
|
130
|
+
{
|
|
131
|
+
Runner.CheckSet(useflags, testspec, testset);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
for (int index = 0; index < testset.Count; index++)
|
|
135
|
+
{
|
|
136
|
+
if (!(testset[index] is IDictionary<string, object> entry))
|
|
137
|
+
{
|
|
138
|
+
throw new OmniError("omni: " + useflags.Name + "[" + index + "]: entry is not a map");
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// An entry with no `out` expects a null (or absent) result.
|
|
142
|
+
if (useflags.Null && (!entry.ContainsKey("out") || null == entry["out"]))
|
|
143
|
+
{
|
|
144
|
+
entry["out"] = Util.NULLMARK;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
Subject entrysubject = subject;
|
|
148
|
+
Provider entryclient = provider;
|
|
149
|
+
|
|
150
|
+
if (entry.ContainsKey("client") && entry["client"] is string clientname)
|
|
151
|
+
{
|
|
152
|
+
if (!clients.ContainsKey(clientname))
|
|
153
|
+
{
|
|
154
|
+
throw new OmniError("omni: unknown client: " + clientname, entry);
|
|
155
|
+
}
|
|
156
|
+
entryclient = clients[clientname];
|
|
157
|
+
var clientsubject = Runner.ResolveSubject(name, entryclient);
|
|
158
|
+
if (null != clientsubject)
|
|
159
|
+
{
|
|
160
|
+
entrysubject = clientsubject;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
object[] args = ResolveArgs(entry, entryclient);
|
|
165
|
+
|
|
166
|
+
object res;
|
|
167
|
+
try
|
|
168
|
+
{
|
|
169
|
+
res = entrysubject(args);
|
|
170
|
+
}
|
|
171
|
+
catch (OmniError)
|
|
172
|
+
{
|
|
173
|
+
throw;
|
|
174
|
+
}
|
|
175
|
+
catch (Exception err)
|
|
176
|
+
{
|
|
177
|
+
Runner.HandleError(useflags, index, entry, err, this.provider);
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
res = Runner.FixJson(res, useflags.Null);
|
|
182
|
+
entry["res"] = res;
|
|
183
|
+
|
|
184
|
+
Runner.CheckResult(useflags, index, entry, args, res);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Build the argument list: `ctx`, `args`, or `in`.
|
|
189
|
+
private object[] ResolveArgs(IDictionary<string, object> entry, Provider client)
|
|
190
|
+
{
|
|
191
|
+
object[] args;
|
|
192
|
+
|
|
193
|
+
bool hasctx = entry.ContainsKey("ctx");
|
|
194
|
+
bool hasargs = entry.ContainsKey("args");
|
|
195
|
+
|
|
196
|
+
if (hasctx)
|
|
197
|
+
{
|
|
198
|
+
args = new object[] { entry["ctx"] };
|
|
199
|
+
}
|
|
200
|
+
else if (hasargs)
|
|
201
|
+
{
|
|
202
|
+
args = entry["args"] is IList<object> list ? list.ToArray() : new object[] { entry["args"] };
|
|
203
|
+
}
|
|
204
|
+
else
|
|
205
|
+
{
|
|
206
|
+
// An entry carrying none of `in`/`args`/`ctx` is called with one
|
|
207
|
+
// ABSENT argument, not with null. Canonical passes `undefined`
|
|
208
|
+
// there and the corpus leans on the difference: `typify()` is
|
|
209
|
+
// 1073741824 where `typify(null)` is 4194432.
|
|
210
|
+
//
|
|
211
|
+
// C# can say it - `Absent.Mark` is already this port's model for
|
|
212
|
+
// "no value" - where python and ruby cannot and contain it in
|
|
213
|
+
// their compat shims instead (register 4.12). Passing null here
|
|
214
|
+
// collapsed the two states before any consumer could see them.
|
|
215
|
+
//
|
|
216
|
+
// No existing consumer changes: fib has 0 implicit entries of 68
|
|
217
|
+
// and sekreto 0 of 110. struct's corpus has 17.
|
|
218
|
+
args = new object[]
|
|
219
|
+
{
|
|
220
|
+
entry.ContainsKey("in") ? Util.Clone(entry["in"]) : Absent.Mark,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if ((hasctx || hasargs) && 0 < args.Length && Util.IsMap(args[0]))
|
|
225
|
+
{
|
|
226
|
+
object first = Util.Clone(args[0]);
|
|
227
|
+
if (null != provider.Contextify)
|
|
228
|
+
{
|
|
229
|
+
first = provider.Contextify(first);
|
|
230
|
+
}
|
|
231
|
+
if (first is IDictionary<string, object> firstmap)
|
|
232
|
+
{
|
|
233
|
+
firstmap["client"] = client;
|
|
234
|
+
}
|
|
235
|
+
args[0] = first;
|
|
236
|
+
entry["ctx"] = first;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return args;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/// <summary>A loaded spec plus its provider.</summary>
|
|
244
|
+
public class RunnerPack
|
|
245
|
+
{
|
|
246
|
+
private readonly object alltests;
|
|
247
|
+
private readonly Provider provider;
|
|
248
|
+
private readonly int specversion;
|
|
249
|
+
|
|
250
|
+
internal RunnerPack(object alltests, Provider provider, int specversion)
|
|
251
|
+
{
|
|
252
|
+
this.alltests = alltests;
|
|
253
|
+
this.provider = provider ?? new Provider();
|
|
254
|
+
this.specversion = specversion;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/// <summary>Resolve one named section of the spec.</summary>
|
|
258
|
+
public RunPack Run(string name, object store = null)
|
|
259
|
+
{
|
|
260
|
+
object spec = Runner.ResolveSpec(name, alltests);
|
|
261
|
+
var clients = Runner.ResolveClients(provider, spec, store);
|
|
262
|
+
var subject = Runner.ResolveSubject(name, provider);
|
|
263
|
+
return new RunPack(spec, subject, provider, clients, name, specversion);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
public static class Runner
|
|
268
|
+
{
|
|
269
|
+
public const string NULLMARK = Util.NULLMARK;
|
|
270
|
+
public const string UNDEFMARK = Util.UNDEFMARK;
|
|
271
|
+
public const string EXISTSMARK = Util.EXISTSMARK;
|
|
272
|
+
|
|
273
|
+
// The newest spec format version this runner understands. A spec
|
|
274
|
+
// with no OMNI block is version 0: the original, lenient format,
|
|
275
|
+
// frozen forever. Version 1 turns on strict entry validation (see
|
|
276
|
+
// CheckEntry).
|
|
277
|
+
public const int SPECVERSION = 1;
|
|
278
|
+
|
|
279
|
+
// Capability strings this runner supports beyond the version
|
|
280
|
+
// baseline. A spec's OMNI.requires list is checked against this: an
|
|
281
|
+
// unknown capability refuses the spec loudly at load time, instead
|
|
282
|
+
// of a lagging port silently mis-running it. (Empty today; future
|
|
283
|
+
// format features mint a string here.)
|
|
284
|
+
public static readonly string[] CAPABILITIES = Array.Empty<string>();
|
|
285
|
+
|
|
286
|
+
// The complete set of fields an entry may carry. Under version 1
|
|
287
|
+
// anything else is an error: an unrecognised key is almost always a
|
|
288
|
+
// typo'd assertion, and a typo'd assertion is a test that silently
|
|
289
|
+
// stopped testing.
|
|
290
|
+
private static readonly string[] ENTRYFIELDS =
|
|
291
|
+
{ "in", "args", "ctx", "out", "err", "match", "client", "id", "doc" };
|
|
292
|
+
|
|
293
|
+
/// <summary>Make a runner for a spec file path and a provider.</summary>
|
|
294
|
+
public static RunnerPack MakeRunner(string path, Provider provider = null)
|
|
295
|
+
{
|
|
296
|
+
object alltests = LoadSpec(path);
|
|
297
|
+
int specversion = ResolveVersion(alltests);
|
|
298
|
+
return new RunnerPack(alltests, provider, specversion);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/// <summary>Make a runner for an in-memory spec and a provider.</summary>
|
|
302
|
+
public static RunnerPack MakeRunner(object spec, Provider provider = null)
|
|
303
|
+
{
|
|
304
|
+
int specversion = ResolveVersion(spec);
|
|
305
|
+
return new RunnerPack(spec, provider, specversion);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/// <summary>Load a spec: a path to a JSON file.</summary>
|
|
309
|
+
public static object LoadSpec(string path)
|
|
310
|
+
{
|
|
311
|
+
if (!File.Exists(path))
|
|
312
|
+
{
|
|
313
|
+
throw new OmniError("omni: cannot read spec: " + path);
|
|
314
|
+
}
|
|
315
|
+
return Util.Parse(File.ReadAllText(path));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Read the spec's format version from its optional top-level OMNI
|
|
319
|
+
// block, and refuse a spec this runner cannot faithfully run: a
|
|
320
|
+
// version newer than SPECVERSION, or a required capability not in
|
|
321
|
+
// CAPABILITIES.
|
|
322
|
+
internal static int ResolveVersion(object alltests)
|
|
323
|
+
{
|
|
324
|
+
if (!(alltests is IDictionary<string, object> allmap) || !allmap.ContainsKey("OMNI"))
|
|
325
|
+
{
|
|
326
|
+
return 0;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
object meta = allmap["OMNI"];
|
|
330
|
+
|
|
331
|
+
if (!(meta is IDictionary<string, object> metamap) ||
|
|
332
|
+
!metamap.ContainsKey("version") ||
|
|
333
|
+
!Util.IsNum(metamap["version"]) ||
|
|
334
|
+
0 != Util.ToNum(metamap["version"]) % 1)
|
|
335
|
+
{
|
|
336
|
+
throw new OmniError("omni: malformed OMNI version block");
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
double version = Util.ToNum(metamap["version"]);
|
|
340
|
+
|
|
341
|
+
if (0 > version || SPECVERSION < version)
|
|
342
|
+
{
|
|
343
|
+
throw new OmniError("omni: unsupported spec version: " + Util.NumStr(version));
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (metamap.ContainsKey("requires"))
|
|
347
|
+
{
|
|
348
|
+
if (!(metamap["requires"] is IList<object> requires))
|
|
349
|
+
{
|
|
350
|
+
throw new OmniError("omni: malformed OMNI requires list");
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
foreach (var cap in requires)
|
|
354
|
+
{
|
|
355
|
+
if (!(cap is string capstr) || !CAPABILITIES.Contains(capstr))
|
|
356
|
+
{
|
|
357
|
+
throw new OmniError("omni: spec requires unsupported capability: " + Util.Stringify(cap));
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return (int)version;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Strict entry validation, applied when the spec declares version 1
|
|
366
|
+
// or later. The lenient format converts each of these mistakes into
|
|
367
|
+
// a silent pass or a dead field; here they fail with the entry
|
|
368
|
+
// named.
|
|
369
|
+
internal static void CheckEntry(Flags flags, int index, object entry)
|
|
370
|
+
{
|
|
371
|
+
if (!(entry is IDictionary<string, object> map))
|
|
372
|
+
{
|
|
373
|
+
throw Fail(flags, index, entry, "entry is not a map");
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
foreach (var key in map.Keys)
|
|
377
|
+
{
|
|
378
|
+
if (!ENTRYFIELDS.Contains(key))
|
|
379
|
+
{
|
|
380
|
+
throw Fail(flags, index, entry, "unknown entry field: " + key);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
int argsources = 0;
|
|
385
|
+
foreach (var key in new[] { "in", "args", "ctx" })
|
|
386
|
+
{
|
|
387
|
+
if (map.ContainsKey(key))
|
|
388
|
+
{
|
|
389
|
+
argsources++;
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (1 < argsources)
|
|
393
|
+
{
|
|
394
|
+
throw Fail(flags, index, entry, "entry has more than one of in, args, ctx");
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
bool haserr = map.ContainsKey("err") && null != map["err"];
|
|
398
|
+
bool hasout = map.ContainsKey("out");
|
|
399
|
+
if (haserr && hasout)
|
|
400
|
+
{
|
|
401
|
+
throw Fail(flags, index, entry, "entry has both err and out");
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (map.ContainsKey("id") && !(map["id"] is string))
|
|
405
|
+
{
|
|
406
|
+
throw Fail(flags, index, entry, "entry id is not a string");
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// Validate a version-1 group up front, against the AUTHORED entries
|
|
411
|
+
// - null-normalisation would otherwise rewrite an authored null
|
|
412
|
+
// (e.g. id: null) into a sentinel string and hide it from
|
|
413
|
+
// validation. A malformed spec is a spec error, not a test result,
|
|
414
|
+
// so it fails before any subject runs.
|
|
415
|
+
internal static void CheckSet(Flags flags, object testspec, IList<object> normalset)
|
|
416
|
+
{
|
|
417
|
+
IList<object> origset = normalset;
|
|
418
|
+
|
|
419
|
+
if (testspec is IDictionary<string, object> specmap &&
|
|
420
|
+
specmap.ContainsKey("set") && specmap["set"] is IList<object> setlist)
|
|
421
|
+
{
|
|
422
|
+
origset = setlist;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
bool markedempty = false;
|
|
426
|
+
if (testspec is IDictionary<string, object> em &&
|
|
427
|
+
em.ContainsKey("empty") && em["empty"] is bool flag)
|
|
428
|
+
{
|
|
429
|
+
markedempty = flag;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (0 == origset.Count && !markedempty)
|
|
433
|
+
{
|
|
434
|
+
throw new OmniError("omni: empty test set: " + flags.Name);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
for (int index = 0; index < origset.Count; index++)
|
|
438
|
+
{
|
|
439
|
+
CheckEntry(flags, index, origset[index]);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
/// <summary>Find `primary.<name>`, then `<name>`, then the whole spec.</summary>
|
|
444
|
+
public static object ResolveSpec(string name, object alltests)
|
|
445
|
+
{
|
|
446
|
+
if (string.IsNullOrEmpty(name))
|
|
447
|
+
{
|
|
448
|
+
return alltests;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (alltests is IDictionary<string, object> allmap)
|
|
452
|
+
{
|
|
453
|
+
if (allmap.ContainsKey("primary") && allmap["primary"] is IDictionary<string, object> primary &&
|
|
454
|
+
primary.ContainsKey(name) && null != primary[name])
|
|
455
|
+
{
|
|
456
|
+
return primary[name];
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
if (allmap.ContainsKey(name) && null != allmap[name])
|
|
460
|
+
{
|
|
461
|
+
return allmap[name];
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
return alltests;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
internal static Dictionary<string, Provider> ResolveClients(Provider provider, object spec, object store)
|
|
469
|
+
{
|
|
470
|
+
var clients = new Dictionary<string, Provider>();
|
|
471
|
+
|
|
472
|
+
if (!(spec is IDictionary<string, object> specmap) ||
|
|
473
|
+
!specmap.ContainsKey("DEF") ||
|
|
474
|
+
!(specmap["DEF"] is IDictionary<string, object> def) ||
|
|
475
|
+
!def.ContainsKey("client") ||
|
|
476
|
+
!(def["client"] is IDictionary<string, object> defclient))
|
|
477
|
+
{
|
|
478
|
+
return clients;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// A spec may define clients that a given test run never references.
|
|
482
|
+
if (null == provider.Client)
|
|
483
|
+
{
|
|
484
|
+
return clients;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
foreach (var entry in defclient)
|
|
488
|
+
{
|
|
489
|
+
object copts = new Dictionary<string, object>();
|
|
490
|
+
|
|
491
|
+
if (entry.Value is IDictionary<string, object> cdef &&
|
|
492
|
+
cdef.ContainsKey("test") &&
|
|
493
|
+
cdef["test"] is IDictionary<string, object> ctest &&
|
|
494
|
+
ctest.ContainsKey("options"))
|
|
495
|
+
{
|
|
496
|
+
copts = Util.Clone(ctest["options"]);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
if (null != provider.Inject && Util.IsMap(store))
|
|
500
|
+
{
|
|
501
|
+
copts = provider.Inject(copts, store);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
clients[entry.Key] = provider.Client(copts);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
return clients;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
internal static Subject ResolveSubject(string name, Provider provider)
|
|
511
|
+
{
|
|
512
|
+
if (string.IsNullOrEmpty(name) || null == provider || null == provider.SubjectFor)
|
|
513
|
+
{
|
|
514
|
+
return null;
|
|
515
|
+
}
|
|
516
|
+
return provider.SubjectFor(name);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/// <summary>Nulls become NULLMARK, errors become {name,message}. Always a copy.</summary>
|
|
520
|
+
public static object FixJson(object val, bool donull)
|
|
521
|
+
{
|
|
522
|
+
if (null == val || Util.IsAbsent(val))
|
|
523
|
+
{
|
|
524
|
+
return donull ? (object)Util.NULLMARK : val;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (val is Exception err)
|
|
528
|
+
{
|
|
529
|
+
return Errify(err);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (val is IList<object> list)
|
|
533
|
+
{
|
|
534
|
+
var outlist = new List<object>();
|
|
535
|
+
foreach (var entry in list)
|
|
536
|
+
{
|
|
537
|
+
outlist.Add(FixJson(entry, donull));
|
|
538
|
+
}
|
|
539
|
+
return outlist;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
if (val is IDictionary<string, object> map)
|
|
543
|
+
{
|
|
544
|
+
var outmap = new Dictionary<string, object>();
|
|
545
|
+
foreach (var entry in map)
|
|
546
|
+
{
|
|
547
|
+
outmap[entry.Key] = FixJson(entry.Value, donull);
|
|
548
|
+
}
|
|
549
|
+
return outmap;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
return val;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/// <summary>The JSON form of an error: always at least {name,message}.</summary>
|
|
556
|
+
public static IDictionary<string, object> Errify(object err)
|
|
557
|
+
{
|
|
558
|
+
var out_ = new Dictionary<string, object>();
|
|
559
|
+
|
|
560
|
+
if (err is Exception exception)
|
|
561
|
+
{
|
|
562
|
+
out_["name"] = exception.GetType().Name;
|
|
563
|
+
out_["message"] = exception.Message;
|
|
564
|
+
}
|
|
565
|
+
else
|
|
566
|
+
{
|
|
567
|
+
out_["name"] = "Error";
|
|
568
|
+
out_["message"] = Convert.ToString(err, CultureInfo.InvariantCulture);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
return out_;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
// The label of one entry, for failure messages.
|
|
575
|
+
private static string EntryRef(Flags flags, int index, object entry)
|
|
576
|
+
{
|
|
577
|
+
string label = string.IsNullOrEmpty(flags.Name) ? "set" : flags.Name;
|
|
578
|
+
string idpart = "";
|
|
579
|
+
if (entry is IDictionary<string, object> map && map.ContainsKey("id") && null != map["id"])
|
|
580
|
+
{
|
|
581
|
+
idpart = " (" + Util.Stringify(map["id"]) + ")";
|
|
582
|
+
}
|
|
583
|
+
return label + "[" + index.ToString(CultureInfo.InvariantCulture) + "]" + idpart;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
internal static OmniError Fail(Flags flags, int index, object entry,
|
|
587
|
+
string reason, string expected = null, string actual = null)
|
|
588
|
+
{
|
|
589
|
+
var msg = new StringBuilder("omni: ").Append(EntryRef(flags, index, entry)).Append(": ").Append(reason);
|
|
590
|
+
|
|
591
|
+
if (null != expected)
|
|
592
|
+
{
|
|
593
|
+
msg.Append("\n expected: ").Append(expected);
|
|
594
|
+
}
|
|
595
|
+
if (null != actual)
|
|
596
|
+
{
|
|
597
|
+
msg.Append("\n actual: ").Append(actual);
|
|
598
|
+
}
|
|
599
|
+
msg.Append("\n entry: ").Append(Util.Stringify(EntrySummary(entry)));
|
|
600
|
+
|
|
601
|
+
return new OmniError(msg.ToString(), entry);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
// The spec-defined part of an entry (drop runner bookkeeping).
|
|
605
|
+
private static object EntrySummary(object entry)
|
|
606
|
+
{
|
|
607
|
+
if (!(entry is IDictionary<string, object> map))
|
|
608
|
+
{
|
|
609
|
+
return entry;
|
|
610
|
+
}
|
|
611
|
+
var out_ = new Dictionary<string, object>();
|
|
612
|
+
foreach (var field in map)
|
|
613
|
+
{
|
|
614
|
+
if ("res" != field.Key && "thrown" != field.Key && "ctx" != field.Key)
|
|
615
|
+
{
|
|
616
|
+
out_[field.Key] = field.Value;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
return out_;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
internal static void CheckResult(Flags flags, int index, IDictionary<string, object> entry,
|
|
623
|
+
object[] args, object res)
|
|
624
|
+
{
|
|
625
|
+
bool matched = false;
|
|
626
|
+
|
|
627
|
+
if (entry.ContainsKey("err") && null != entry["err"])
|
|
628
|
+
{
|
|
629
|
+
throw Fail(flags, index, entry, "expected error did not occur",
|
|
630
|
+
Util.Stringify(entry["err"]), Util.Stringify(res));
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
if (entry.ContainsKey("match") && null != entry["match"])
|
|
634
|
+
{
|
|
635
|
+
var base_ = new Dictionary<string, object>
|
|
636
|
+
{
|
|
637
|
+
["in"] = entry.ContainsKey("in") ? entry["in"] : null,
|
|
638
|
+
["args"] = new List<object>(args),
|
|
639
|
+
["out"] = entry.ContainsKey("res") ? entry["res"] : null,
|
|
640
|
+
["ctx"] = entry.ContainsKey("ctx") ? entry["ctx"] : null,
|
|
641
|
+
};
|
|
642
|
+
Match(flags, index, entry, entry["match"], base_);
|
|
643
|
+
matched = true;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// Same conflation as ResolveArgs: an entry with NO `out` expects an
|
|
647
|
+
// absent result, and one with `out: null` expects a null. Answering
|
|
648
|
+
// null for both compared a subject that correctly returned nothing
|
|
649
|
+
// against null and marked it wrong. Canonical gets this for free -
|
|
650
|
+
// `entry.out` on a missing key IS undefined, which is also how
|
|
651
|
+
// TypeScript spells absent.
|
|
652
|
+
//
|
|
653
|
+
// This half was missing while FixJson stopped collapsing absent
|
|
654
|
+
// into null (#23), and the two must agree: with only FixJson fixed,
|
|
655
|
+
// a subject that returned absent produced `res` absent and `out`
|
|
656
|
+
// null, so `minor/clone#13` failed.
|
|
657
|
+
//
|
|
658
|
+
// (Under `null: true` this never fires - ResolveEntry has already
|
|
659
|
+
// put NULLMARK there.)
|
|
660
|
+
object outval = entry.ContainsKey("out") ? entry["out"] : Absent.Mark;
|
|
661
|
+
|
|
662
|
+
if (Util.DeepEqual(res, outval))
|
|
663
|
+
{
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
// NOTE: a match with no explicit out is a complete check on its own.
|
|
668
|
+
// `null == out` in canonical is true of undefined too, so absent counts.
|
|
669
|
+
if (matched && (Util.NULLMARK.Equals(outval) || null == outval || Util.IsAbsent(outval)))
|
|
670
|
+
{
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
throw Fail(flags, index, entry, "result mismatch", Util.Stringify(outval), Util.Stringify(res));
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
/// <summary>The error base a <c>match.err</c> sees: the provider's own, when it has one.</summary>
|
|
678
|
+
internal static object ErrBase(object err, Provider provider)
|
|
679
|
+
{
|
|
680
|
+
return null != provider && null != provider.Errify ? provider.Errify(err) : Errify(err);
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
internal static void HandleError(Flags flags, int index, IDictionary<string, object> entry, Exception err, Provider provider = null)
|
|
684
|
+
{
|
|
685
|
+
object entryerr = entry.ContainsKey("err") ? entry["err"] : null;
|
|
686
|
+
|
|
687
|
+
if (null != entryerr)
|
|
688
|
+
{
|
|
689
|
+
bool istrue = entryerr is bool flag && flag;
|
|
690
|
+
|
|
691
|
+
if (istrue || MatchVal(entryerr, err.Message))
|
|
692
|
+
{
|
|
693
|
+
if (entry.ContainsKey("match") && null != entry["match"])
|
|
694
|
+
{
|
|
695
|
+
var base_ = new Dictionary<string, object>
|
|
696
|
+
{
|
|
697
|
+
["in"] = entry.ContainsKey("in") ? entry["in"] : null,
|
|
698
|
+
["out"] = entry.ContainsKey("res") ? entry["res"] : null,
|
|
699
|
+
["ctx"] = entry.ContainsKey("ctx") ? entry["ctx"] : null,
|
|
700
|
+
["err"] = ErrBase(err, provider),
|
|
701
|
+
};
|
|
702
|
+
Match(flags, index, entry, entry["match"], base_);
|
|
703
|
+
}
|
|
704
|
+
return;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
throw Fail(flags, index, entry, "error mismatch", Util.Stringify(entryerr), err.Message);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
throw Fail(flags, index, entry, "unexpected error", null, err.Message);
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
/// <summary>Check that every leaf of `check` is present, and matches, in `base`.</summary>
|
|
714
|
+
public static void Match(Flags flags, int index, IDictionary<string, object> entry,
|
|
715
|
+
object check, object base_)
|
|
716
|
+
{
|
|
717
|
+
MatchWalk(flags, index, entry, check, base_, new List<string>());
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
private static void MatchWalk(Flags flags, int index, IDictionary<string, object> entry,
|
|
721
|
+
object check, object base_, List<string> path)
|
|
722
|
+
{
|
|
723
|
+
string where = 0 == path.Count ? "<root>" : Util.PathIfy(path);
|
|
724
|
+
|
|
725
|
+
if (check is IList<object> list)
|
|
726
|
+
{
|
|
727
|
+
for (int at = 0; at < list.Count; at++)
|
|
728
|
+
{
|
|
729
|
+
var childpath = new List<string>(path) { at.ToString(CultureInfo.InvariantCulture) };
|
|
730
|
+
MatchWalk(flags, index, entry, list[at], base_, childpath);
|
|
731
|
+
}
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
if (check is IDictionary<string, object> map)
|
|
736
|
+
{
|
|
737
|
+
foreach (var field in map)
|
|
738
|
+
{
|
|
739
|
+
var childpath = new List<string>(path) { field.Key };
|
|
740
|
+
MatchWalk(flags, index, entry, field.Value, base_, childpath);
|
|
741
|
+
}
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
object baseval = Util.GetPath(base_, path);
|
|
746
|
+
|
|
747
|
+
// The sentinels are tested BEFORE the identity check below.
|
|
748
|
+
// Otherwise a subject returning the literal string "__UNDEF__"
|
|
749
|
+
// satisfies an assertion that the key is absent - two mutually
|
|
750
|
+
// exclusive states passing one check. A sentinel that accepts
|
|
751
|
+
// its own literal is not a sentinel. (NULLMARK still accepts
|
|
752
|
+
// NULLMARK: under the default null flag a real null has already
|
|
753
|
+
// been normalised to it, so the two are genuinely
|
|
754
|
+
// indistinguishable here - that one needs a raw-value escape,
|
|
755
|
+
// not an ordering change.)
|
|
756
|
+
|
|
757
|
+
// Explicitly absent: satisfied only by a genuinely missing key,
|
|
758
|
+
// never by a present null (the distinction the sentinels exist
|
|
759
|
+
// to keep).
|
|
760
|
+
if (Util.UNDEFMARK.Equals(check))
|
|
761
|
+
{
|
|
762
|
+
if (Util.IsAbsent(baseval))
|
|
763
|
+
{
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
throw Fail(flags, index, entry, "expected absent at " + where,
|
|
767
|
+
"absent", Util.Stringify(baseval));
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// Explicitly null: satisfied only by a present null.
|
|
771
|
+
if (Util.NULLMARK.Equals(check))
|
|
772
|
+
{
|
|
773
|
+
if (null == baseval || Util.NULLMARK.Equals(baseval))
|
|
774
|
+
{
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
throw Fail(flags, index, entry, "expected null at " + where,
|
|
778
|
+
"null", Util.Stringify(baseval));
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
// Explicitly present: any present value, including null.
|
|
782
|
+
if (Util.EXISTSMARK.Equals(check))
|
|
783
|
+
{
|
|
784
|
+
if (!Util.IsAbsent(baseval))
|
|
785
|
+
{
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
788
|
+
throw Fail(flags, index, entry, "expected present at " + where,
|
|
789
|
+
"present", "absent");
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// Identical values match. This sits below the sentinel branches
|
|
793
|
+
// on purpose - see the note above.
|
|
794
|
+
if (Util.DeepEqual(check, baseval))
|
|
795
|
+
{
|
|
796
|
+
return;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
// A concrete expectation never matches a missing key - a match
|
|
800
|
+
// leaf against an absent value must fail, not substring-match
|
|
801
|
+
// "undefined".
|
|
802
|
+
if (Util.IsAbsent(baseval))
|
|
803
|
+
{
|
|
804
|
+
throw Fail(flags, index, entry, "match failed at " + where,
|
|
805
|
+
Util.Stringify(check), "absent");
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
if (MatchVal(check, baseval))
|
|
809
|
+
{
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
throw Fail(flags, index, entry, "match failed at " + where,
|
|
814
|
+
Util.Stringify(check), Util.Stringify(baseval));
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
/// <summary>Match one leaf: /regex/ or case-insensitive substring for strings.</summary>
|
|
818
|
+
public static bool MatchVal(object check, object base_)
|
|
819
|
+
{
|
|
820
|
+
if (Util.DeepEqual(check, base_))
|
|
821
|
+
{
|
|
822
|
+
return true;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
if (check is string text)
|
|
826
|
+
{
|
|
827
|
+
// An empty want would substring-match anything.
|
|
828
|
+
if (0 == text.Length)
|
|
829
|
+
{
|
|
830
|
+
return false;
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
string basestr = Util.Stringify(base_);
|
|
834
|
+
|
|
835
|
+
if (2 < text.Length && text.StartsWith("/", StringComparison.Ordinal) &&
|
|
836
|
+
text.EndsWith("/", StringComparison.Ordinal))
|
|
837
|
+
{
|
|
838
|
+
try
|
|
839
|
+
{
|
|
840
|
+
return Regex.IsMatch(basestr, text.Substring(1, text.Length - 2));
|
|
841
|
+
}
|
|
842
|
+
catch (ArgumentException)
|
|
843
|
+
{
|
|
844
|
+
return false;
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
return basestr.ToLowerInvariant().Contains(text.ToLowerInvariant());
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
return Util.DeepEqual(check, base_);
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
/// <summary>Convert NULLMARK sentinels back into real nulls.</summary>
|
|
855
|
+
public static object NullModifier(object val, IList<string> path)
|
|
856
|
+
{
|
|
857
|
+
if (val is string text)
|
|
858
|
+
{
|
|
859
|
+
return Util.NULLMARK == text ? null : (object)text.Replace(Util.NULLMARK, "null");
|
|
860
|
+
}
|
|
861
|
+
return val;
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
}
|