@voxgig/sdkgen 4.8.3 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/package.json +1 -1
  3. package/project/.sdk/model/target/zig.aon +9 -0
  4. package/project/.sdk/src/cmp/zig/Package_zig.ts +15 -11
  5. package/project/.sdk/src/cmp/zig/fragment/Entity.fragment.zig +3 -3
  6. package/project/.sdk/src/cmp/zig/fragment/EntityListOp.fragment.zig +3 -3
  7. package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +3 -3
  8. package/project/.sdk/src/cmp/zig/utility_zig.ts +50 -1
  9. package/project/.sdk/tm/c/tests/vendor/omni/json.c +2 -2
  10. package/project/.sdk/tm/c/tests/vendor/omni/omni.h +2 -2
  11. package/project/.sdk/tm/c/tests/vendor/omni/runner.c +2 -2
  12. package/project/.sdk/tm/c/tests/vendor/omni/util.c +2 -2
  13. package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/json.clj +2 -2
  14. package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/runner.clj +2 -2
  15. package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/util.clj +2 -2
  16. package/project/.sdk/tm/cpp/test/vendor/omni/json.hpp +2 -2
  17. package/project/.sdk/tm/cpp/test/vendor/omni/omni.hpp +2 -2
  18. package/project/.sdk/tm/cpp/test/vendor/omni/util.hpp +2 -2
  19. package/project/.sdk/tm/csharp/test/vendor/omni/Runner.cs +2 -2
  20. package/project/.sdk/tm/csharp/test/vendor/omni/Util.cs +2 -2
  21. package/project/.sdk/tm/csharp/utility/struct/Struct.cs +1 -1
  22. package/project/.sdk/tm/dart/test/vendor/omni/omni.dart +2 -2
  23. package/project/.sdk/tm/dart/test/vendor/omni/runner.dart +2 -2
  24. package/project/.sdk/tm/dart/test/vendor/omni/util.dart +2 -2
  25. package/project/.sdk/tm/elixir/test/vendor/omni/json.ex +2 -2
  26. package/project/.sdk/tm/elixir/test/vendor/omni/runner.ex +2 -2
  27. package/project/.sdk/tm/elixir/test/vendor/omni/util.ex +2 -2
  28. package/project/.sdk/tm/go/feature/secrets/plugin/capability.go +1 -1
  29. package/project/.sdk/tm/go/feature/secrets/plugin/catalog.go +1 -1
  30. package/project/.sdk/tm/go/feature/secrets/plugin/config.go +1 -1
  31. package/project/.sdk/tm/go/feature/secrets/plugin/depend.go +1 -1
  32. package/project/.sdk/tm/go/feature/secrets/plugin/env.go +1 -1
  33. package/project/.sdk/tm/go/feature/secrets/plugin/export.go +1 -1
  34. package/project/.sdk/tm/go/feature/secrets/plugin/graph.go +1 -1
  35. package/project/.sdk/tm/go/feature/secrets/plugin/host.go +1 -1
  36. package/project/.sdk/tm/go/feature/secrets/plugin/order.go +1 -1
  37. package/project/.sdk/tm/go/feature/secrets/plugin/point.go +1 -1
  38. package/project/.sdk/tm/go/feature/secrets/plugin/ref.go +1 -1
  39. package/project/.sdk/tm/go/feature/secrets/plugin/resolve.go +1 -1
  40. package/project/.sdk/tm/go/feature/secrets/plugin/types.go +1 -1
  41. package/project/.sdk/tm/go/feature/secrets/plugin/util.go +1 -1
  42. package/project/.sdk/tm/go/feature/secrets/plugin/version.go +1 -1
  43. package/project/.sdk/tm/go/feature/secrets/plugins/aws/aws.go +4 -4
  44. package/project/.sdk/tm/go/feature/secrets/plugins/aws/sigv4.go +2 -2
  45. package/project/.sdk/tm/go/feature/secrets/plugins/azuresecrets/azuresecrets.go +2 -2
  46. package/project/.sdk/tm/go/feature/secrets/plugins/boru/boru.go +2 -2
  47. package/project/.sdk/tm/go/feature/secrets/plugins/doppler/doppler.go +2 -2
  48. package/project/.sdk/tm/go/feature/secrets/plugins/gcpsecrets/gcpsecrets.go +2 -2
  49. package/project/.sdk/tm/go/feature/secrets/plugins/hashicorp/hashicorp.go +4 -5
  50. package/project/.sdk/tm/go/feature/secrets/plugins/httpjson/httpjson.go +3 -3
  51. package/project/.sdk/tm/go/feature/secrets/plugins/infisical/infisical.go +3 -4
  52. package/project/.sdk/tm/go/feature/secrets/plugins/onepassword/onepassword.go +2 -2
  53. package/project/.sdk/tm/go/feature/secrets/plugins/secretspec/secretspec.go +2 -2
  54. package/project/.sdk/tm/go/feature/secrets/sekreto/addr.go +2 -2
  55. package/project/.sdk/tm/go/feature/secrets/sekreto/providers.go +5 -2
  56. package/project/.sdk/tm/go/feature/secrets/sekreto/sekreto.go +31 -2
  57. package/project/.sdk/tm/go/test/omni/omni.go +8 -3
  58. package/project/.sdk/tm/go/test/omni/util.go +25 -4
  59. package/project/.sdk/tm/go/utility/struct/voxgigstruct.go +1 -1
  60. package/project/.sdk/tm/java/test/vendor/omni/Json.java +2 -2
  61. package/project/.sdk/tm/java/test/vendor/omni/Runner.java +2 -2
  62. package/project/.sdk/tm/java/test/vendor/omni/Util.java +2 -2
  63. package/project/.sdk/tm/java/utility/struct/Struct.java +1 -1
  64. package/project/.sdk/tm/js/src/utility/StructUtility.js +2 -2
  65. package/project/.sdk/tm/js/test/vendor/omni/index.js +1 -1
  66. package/project/.sdk/tm/js/test/vendor/omni/runner.js +18 -3
  67. package/project/.sdk/tm/js/test/vendor/omni/util.js +25 -8
  68. package/project/.sdk/tm/kotlin/test/vendor/omni/Json.kt +2 -2
  69. package/project/.sdk/tm/kotlin/test/vendor/omni/Runner.kt +2 -2
  70. package/project/.sdk/tm/kotlin/test/vendor/omni/Util.kt +2 -2
  71. package/project/.sdk/tm/kotlin/utility/struct/Struct.kt +1 -1
  72. package/project/.sdk/tm/lean/test/vendor/omni/Omni.lean +2 -2
  73. package/project/.sdk/tm/lua/test/vendor/omni/json.lua +2 -2
  74. package/project/.sdk/tm/lua/test/vendor/omni/regex.lua +2 -2
  75. package/project/.sdk/tm/lua/test/vendor/omni/runner.lua +2 -2
  76. package/project/.sdk/tm/lua/test/vendor/omni/util.lua +2 -2
  77. package/project/.sdk/tm/lua/utility/struct/regex.lua +1 -1
  78. package/project/.sdk/tm/lua/utility/struct/struct.lua +1 -1
  79. package/project/.sdk/tm/ocaml/test/vendor/omni/omni.ml +2 -2
  80. package/project/.sdk/tm/perl/lib/Voxgig/Struct.pm +1 -1
  81. package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni/Runner.pm +1 -1
  82. package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni/Util.pm +1 -1
  83. package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni.pm +1 -1
  84. package/project/.sdk/tm/php/test/vendor/omni/Runner.php +2 -2
  85. package/project/.sdk/tm/php/test/vendor/omni/Util.php +2 -2
  86. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/__init__.py +1 -1
  87. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/capability.py +1 -1
  88. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/catalog.py +1 -1
  89. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/config.py +1 -1
  90. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/depend.py +1 -1
  91. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/env.py +1 -1
  92. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/export.py +1 -1
  93. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/graph.py +1 -1
  94. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/host.py +1 -1
  95. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/order.py +1 -1
  96. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/point.py +1 -1
  97. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/ref.py +1 -1
  98. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/resolve.py +1 -1
  99. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/types.py +1 -1
  100. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/version.py +1 -1
  101. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/__init__.py +3 -1
  102. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/addr.py +1 -1
  103. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/aws.py +3 -3
  104. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/azuresecrets.py +1 -1
  105. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/boru.py +1 -1
  106. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/doppler.py +1 -1
  107. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/gcpsecrets.py +1 -1
  108. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/hashicorp.py +3 -4
  109. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/httpjson.py +1 -1
  110. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/infisical.py +4 -6
  111. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/onepassword.py +1 -1
  112. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/secretspec.py +1 -1
  113. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/sigv4.py +1 -1
  114. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/providers.py +1 -1
  115. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/sekreto.py +21 -1
  116. package/project/.sdk/tm/py/pkg/utility/voxgig_struct/voxgig_struct.py +1 -1
  117. package/project/.sdk/tm/py/test/voxgig_omni/__init__.py +1 -1
  118. package/project/.sdk/tm/py/test/voxgig_omni/runner.py +16 -2
  119. package/project/.sdk/tm/py/test/voxgig_omni/util.py +27 -12
  120. package/project/.sdk/tm/rb/test/vendor/omni/runner.rb +2 -2
  121. package/project/.sdk/tm/rb/test/vendor/omni/util.rb +2 -2
  122. package/project/.sdk/tm/rb/test/vendor/omni/voxgig_omni.rb +2 -2
  123. package/project/.sdk/tm/rust/tests/vendor/omni/json.rs +2 -2
  124. package/project/.sdk/tm/rust/tests/vendor/omni/mod.rs +2 -2
  125. package/project/.sdk/tm/rust/tests/vendor/omni/regex.rs +2 -2
  126. package/project/.sdk/tm/rust/tests/vendor/omni/runner.rs +2 -2
  127. package/project/.sdk/tm/rust/tests/vendor/omni/util.rs +2 -2
  128. package/project/.sdk/tm/scala/sdktest/vendor/omni/Json.scala +2 -2
  129. package/project/.sdk/tm/scala/sdktest/vendor/omni/Runner.scala +2 -2
  130. package/project/.sdk/tm/scala/sdktest/vendor/omni/Util.scala +2 -2
  131. package/project/.sdk/tm/swift/Tests/vendor/omni/Json.swift +2 -2
  132. package/project/.sdk/tm/swift/Tests/vendor/omni/Runner.swift +2 -2
  133. package/project/.sdk/tm/swift/Tests/vendor/omni/Util.swift +2 -2
  134. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Capability.ts +1 -1
  135. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Catalog.ts +1 -1
  136. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Config.ts +1 -1
  137. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Depend.ts +1 -1
  138. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Env.ts +1 -1
  139. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Export.ts +1 -1
  140. package/project/.sdk/tm/ts/src/feature/secrets/plugin/FeatureHost.ts +1 -1
  141. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Graph.ts +1 -1
  142. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Host.ts +1 -1
  143. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Order.ts +1 -1
  144. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Point.ts +1 -1
  145. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Ref.ts +1 -1
  146. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Resolve.ts +1 -1
  147. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Types.ts +1 -1
  148. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Version.ts +1 -1
  149. package/project/.sdk/tm/ts/src/feature/secrets/plugin/index.ts +1 -1
  150. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sekreto.ts +1 -1
  151. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/index.ts +1 -1
  152. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/aws.ts +1 -1
  153. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/azuresecrets.ts +1 -1
  154. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/boru.ts +1 -1
  155. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/doppler.ts +1 -1
  156. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/gcpsecrets.ts +1 -1
  157. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/hashicorp.ts +1 -1
  158. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/httpjson.ts +1 -1
  159. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/infisical.ts +1 -1
  160. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/onepassword.ts +1 -1
  161. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/secretspec.ts +1 -1
  162. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/sigv4.ts +1 -1
  163. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/addr.ts +1 -1
  164. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/builtin.ts +1 -1
  165. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/dotenv.ts +1 -1
  166. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/env.ts +1 -1
  167. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/file.ts +1 -1
  168. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/memory.ts +1 -1
  169. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/support.ts +1 -1
  170. package/project/.sdk/tm/ts/src/utility/StructUtility.ts +2 -2
  171. package/project/.sdk/tm/ts/test/vendor/omni/Runner.ts +1 -1
  172. package/project/.sdk/tm/ts/test/vendor/omni/Util.ts +1 -1
  173. package/project/.sdk/tm/ts/test/vendor/omni/index.ts +1 -1
  174. package/project/.sdk/tm/zig/Makefile +15 -1
  175. package/project/.sdk/tm/zig/build.zig +23 -5
  176. package/project/.sdk/tm/zig/core/helpers.zig +52 -11
  177. package/project/.sdk/tm/zig/core/mem.zig +17 -1
  178. package/project/.sdk/tm/zig/core/utility.zig +23 -19
  179. package/project/.sdk/tm/zig/feature/audit.zig +2 -2
  180. package/project/.sdk/tm/zig/feature/cache.zig +2 -2
  181. package/project/.sdk/tm/zig/feature/debug.zig +5 -5
  182. package/project/.sdk/tm/zig/feature/netsim.zig +2 -2
  183. package/project/.sdk/tm/zig/feature/paging.zig +2 -2
  184. package/project/.sdk/tm/zig/feature/proxy.zig +15 -8
  185. package/project/.sdk/tm/zig/feature/streaming.zig +5 -5
  186. package/project/.sdk/tm/zig/feature/support.zig +3 -3
  187. package/project/.sdk/tm/zig/feature/telemetry.zig +5 -5
  188. package/project/.sdk/tm/zig/feature/test.zig +10 -5
  189. package/project/.sdk/tm/zig/test/fh.zig +10 -10
  190. package/project/.sdk/tm/zig/test/gotcha_test.zig +5 -5
  191. package/project/.sdk/tm/zig/test/omniresolver.zig +515 -0
  192. package/project/.sdk/tm/zig/test/omnismoke_test.zig +284 -0
  193. package/project/.sdk/tm/zig/test/pipeline_test.zig +8 -8
  194. package/project/.sdk/tm/zig/test/primary_utility_test.zig +144 -154
  195. package/project/.sdk/tm/zig/test/struct_corpus.zig +264 -187
  196. package/project/.sdk/tm/zig/test/vendor/omni/omni.zig +1314 -0
  197. package/project/.sdk/tm/zig/test/vendor/omni/regex.zig +446 -0
  198. package/project/.sdk/tm/zig/utility/voxgigstruct/regex.zig +7 -4
  199. package/project/.sdk/tm/zig/utility/voxgigstruct/struct.zig +356 -157
  200. package/project/sdkgen-package.json +1 -1
  201. package/project/.sdk/tm/zig/test/struct_runner.zig +0 -465
@@ -3,7 +3,7 @@
3
3
  "package": 1
4
4
  },
5
5
  "name": "@voxgig/sdkgen",
6
- "version": "4.8.3",
6
+ "version": "4.9.0",
7
7
  "provides": {
8
8
  "target": [
9
9
  "c",
@@ -1,465 +0,0 @@
1
- // Test runner for Zig — loads build/test/test.json and drives specs
2
- // against subject functions, mirroring the TS/Go runner pattern.
3
-
4
- const std = @import("std");
5
- const voxgig_struct = @import("voxgig-struct");
6
-
7
- const Allocator = std.mem.Allocator;
8
- const StdJsonValue = std.json.Value;
9
- const JsonValue = voxgig_struct.JsonValue;
10
-
11
- pub const NULLMARK = "__NULL__";
12
- pub const UNDEFMARK = "__UNDEF__";
13
- pub const EXISTSMARK = "__EXISTS__";
14
-
15
- pub const TEST_JSON_FILE = "../.sdk/test/test.json";
16
-
17
- // Subject that takes only a std.json.Value (for simple is* functions).
18
- pub const Subject = *const fn (StdJsonValue) StdJsonValue;
19
-
20
- // Subject that takes an allocator and our JsonValue type.
21
- pub const AllocSubject = *const fn (Allocator, JsonValue) JsonValue;
22
-
23
- /// A subject that receives the whole corpus ENTRY and returns std.json.
24
- ///
25
- /// `published` is an out-parameter for the context the subject built. std.json
26
- /// maps cannot be mutated in place safely from here — a put may reallocate the
27
- /// backing store and the caller would never see it — so a section that needs a
28
- /// `match: ctx.*` assertion hands its ctx back through this instead.
29
- pub const EntrySubject = *const fn (
30
- Allocator,
31
- StdJsonValue,
32
- *?StdJsonValue,
33
- /// The SDK's own error message. Zig errors carry no payload, so
34
- /// @errorName gives the tag ("Sdk") and never the text the corpus matches
35
- /// on. A subject that fails writes ctx.pending_err's message here.
36
- *?[]const u8,
37
- ) anyerror!StdJsonValue;
38
-
39
- pub const Spec = struct {
40
- data: StdJsonValue,
41
-
42
- pub fn get(self: Spec, key: []const u8) ?StdJsonValue {
43
- return switch (self.data) {
44
- .object => |obj| obj.get(key),
45
- else => null,
46
- };
47
- }
48
- };
49
-
50
- pub const RunPack = struct {
51
- spec: Spec,
52
- allocator: Allocator,
53
- file_data: []const u8,
54
- /// Cases actually executed, so a suite can assert it ran something.
55
- ran: usize = 0,
56
- parsed: std.json.Parsed(StdJsonValue),
57
-
58
- /// Run all entries in testspec.set against the subject function (no alloc, std types).
59
- pub fn runset(self: RunPack, testspec: StdJsonValue, subject: Subject) !void {
60
- try self.runsetflags(testspec, .{}, subject);
61
- }
62
-
63
- /// Run with flags (e.g. .{ .null_flag = false }).
64
- pub fn runsetflags(self: RunPack, testspec: StdJsonValue, flags: Flags, subject: Subject) !void {
65
- _ = self;
66
- const set = switch (testspec) {
67
- .object => |obj| obj.get("set") orelse return error.NoSetInSpec,
68
- else => return error.SpecNotObject,
69
- };
70
- const entries = switch (set) {
71
- .array => |arr| arr.items,
72
- else => return error.SetNotArray,
73
- };
74
-
75
- for (entries) |entry_val| {
76
- const entry = switch (entry_val) {
77
- .object => |obj| obj,
78
- else => continue,
79
- };
80
-
81
- const in_val: StdJsonValue = entry.get("in") orelse .null;
82
- const raw_out = entry.get("out");
83
- const expected: StdJsonValue = if (raw_out) |o| o else if (flags.null_flag) StdJsonValue{ .string = NULLMARK } else .null;
84
- const err_field = entry.get("err");
85
-
86
- const result = subject(in_val);
87
- if (err_field != null) continue;
88
- try checkResult(expected, result);
89
- }
90
- }
91
-
92
- /// Run all entries against an allocator-aware subject (uses our JsonValue type).
93
- pub fn runsetAlloc(self: RunPack, testspec: StdJsonValue, subject: AllocSubject) !void {
94
- try self.runsetAllocFlags(testspec, .{}, subject);
95
- }
96
-
97
- /// Run with flags against an allocator-aware subject.
98
- pub fn runsetAllocFlags(self: RunPack, testspec: StdJsonValue, flags: Flags, subject: AllocSubject) !void {
99
- const set = switch (testspec) {
100
- .object => |obj| obj.get("set") orelse return error.NoSetInSpec,
101
- else => return error.SpecNotObject,
102
- };
103
- const entries = switch (set) {
104
- .array => |arr| arr.items,
105
- else => return error.SetNotArray,
106
- };
107
-
108
- for (entries, 0..) |entry_val, entry_idx| {
109
- const entry = switch (entry_val) {
110
- .object => |obj| obj,
111
- else => continue,
112
- };
113
-
114
- const has_in = entry.get("in") != null;
115
- const in_val_std: StdJsonValue = entry.get("in") orelse
116
- if (flags.undef_as_null) .null else StdJsonValue{ .string = UNDEFMARK };
117
-
118
- const raw_out = entry.get("out");
119
- const expected: StdJsonValue = if (raw_out) |o| o else if (flags.null_flag) StdJsonValue{ .string = NULLMARK } else .null;
120
-
121
- const err_field = entry.get("err");
122
- _ = has_in;
123
-
124
- // Use an arena allocator for each test case.
125
- var arena = std.heap.ArenaAllocator.init(self.allocator);
126
- defer arena.deinit();
127
- const alloc = arena.allocator();
128
-
129
- // Convert std.json input to our JsonValue type.
130
- const in_val = voxgig_struct.fromStdJson(alloc, in_val_std) catch .null;
131
-
132
- const result_jval = subject(alloc, in_val);
133
-
134
- if (err_field != null) continue;
135
-
136
- // Convert our result back to std.json for comparison.
137
- const result = voxgig_struct.toStdJson(alloc, result_jval) catch StdJsonValue{ .null = {} };
138
-
139
- checkResult(expected, result) catch |e| {
140
- std.debug.print(" [test entry {d}]\n", .{entry_idx});
141
- return e;
142
- };
143
- }
144
- }
145
-
146
- /// Drive a section whose entries carry ctx/args/match/err.
147
- ///
148
- /// The subject receives the whole ENTRY, not the resolved args, because an
149
- /// args-style section has to publish the context it builds back onto the
150
- /// entry — a `match: ctx.*` assertion reads it from there.
151
- pub fn runsetEntry(self: *RunPack, testspec: StdJsonValue, subject: EntrySubject) !void {
152
- const set_val = switch (testspec) {
153
- .object => |obj| obj.get("set") orelse return,
154
- else => return,
155
- };
156
- if (set_val != .array) return;
157
-
158
- var failures: usize = 0;
159
-
160
- for (set_val.array.items, 0..) |entry_val, entry_idx| {
161
- if (entry_val != .object) continue;
162
- const entry = entry_val.object;
163
-
164
- var arena = std.heap.ArenaAllocator.init(self.allocator);
165
- defer arena.deinit();
166
- const alloc = arena.allocator();
167
-
168
- const err_field = entry.get("err");
169
-
170
- self.ran += 1;
171
- var published: ?StdJsonValue = null;
172
- var errmsg: ?[]const u8 = null;
173
-
174
- const res = subject(alloc, entry_val, &published, &errmsg) catch |e| {
175
- // An expected error: match its text, then any `match` block.
176
- if (err_field) |ef| {
177
- const msg = errmsg orelse @errorName(e);
178
- if (ef == .bool and ef.bool) continue;
179
- if (matchval(alloc, ef, StdJsonValue{ .string = msg })) continue;
180
- std.debug.print("\n ERROR MATCH [entry {d}]: [{s}] <=> [{s}]\n", .{
181
- entry_idx, fmtJson(ef), msg,
182
- });
183
- }
184
- failures += 1;
185
- continue;
186
- };
187
-
188
- if (err_field != null) {
189
- std.debug.print("\n expected an error [entry {d}]\n", .{entry_idx});
190
- failures += 1;
191
- continue;
192
- }
193
-
194
- var matched = false;
195
-
196
- if (entry.get("match")) |m| {
197
- var subj = std.json.ObjectMap.init(alloc);
198
- subj.put("out", res) catch {};
199
- if (entry.get("in")) |v| subj.put("in", v) catch {};
200
- if (published) |p| {
201
- subj.put("ctx", p) catch {};
202
- } else if (entry.get("ctx")) |v| {
203
- subj.put("ctx", v) catch {};
204
- }
205
- const subjval = StdJsonValue{ .object = subj };
206
-
207
- var path = std.ArrayList([]const u8).init(alloc);
208
- doMatch(alloc, m, subjval, &path) catch {
209
- std.debug.print(" [entry {d}]\n", .{entry_idx});
210
- failures += 1;
211
- continue;
212
- };
213
- matched = true;
214
- }
215
-
216
- const raw_out = entry.get("out");
217
-
218
- if (raw_out) |o| {
219
- if (jsonEqual(o, res)) continue;
220
- if (o == .string and std.mem.eql(u8, o.string, NULLMARK) and res == .null) continue;
221
- std.debug.print("\n FAIL [entry {d}]: expected {s} got {s}\n", .{
222
- entry_idx, fmtJson(o), fmtJson(res),
223
- });
224
- failures += 1;
225
- } else if (!matched) {
226
- // NO `out` MEANS EXPECT NULL, not "assert nothing". The
227
- // reference sets a missing out to the null marker before
228
- // running, so an entry like {"ctx": {"opname": "bad"}} asserts
229
- // that the utility yields nothing.
230
- if (res == .null) continue;
231
- std.debug.print("\n FAIL [entry {d}]: expected null got {s}\n", .{
232
- entry_idx, fmtJson(res),
233
- });
234
- failures += 1;
235
- }
236
- }
237
-
238
- if (0 < failures) return error.SectionFailed;
239
- }
240
-
241
- pub fn deinit(self: *RunPack) void {
242
- self.parsed.deinit();
243
- self.allocator.free(self.file_data);
244
- }
245
- };
246
-
247
- pub const Flags = struct {
248
- null_flag: bool = true,
249
- undef_as_null: bool = true,
250
- };
251
-
252
- /// Load test.json and return a named top-level spec section.
253
- ///
254
- /// makeRunner is this with "struct" baked in. The primary-utility suite needs
255
- /// "primary" from the same file, and duplicating the load would give the two
256
- /// suites separate copies of a corpus that is meant to be shared.
257
- pub fn makeRunnerFor(allocator: Allocator, section: []const u8) !RunPack {
258
- const data = try std.fs.cwd().readFileAlloc(allocator, TEST_JSON_FILE, 10 * 1024 * 1024);
259
- const parsed = try std.json.parseFromSlice(StdJsonValue, allocator, data, .{});
260
- const root = parsed.value;
261
-
262
- const spec_val = switch (root) {
263
- .object => |obj| obj.get(section) orelse return error.NoSectionInTestJson,
264
- else => return error.TestJsonNotObject,
265
- };
266
-
267
- return RunPack{
268
- .spec = Spec{ .data = spec_val },
269
- .allocator = allocator,
270
- .file_data = data,
271
- .parsed = parsed,
272
- };
273
- }
274
-
275
- /// Load test.json and return the "struct" spec.
276
- pub fn makeRunner(allocator: Allocator) !RunPack {
277
- const path = TEST_JSON_FILE;
278
- const data = try std.fs.cwd().readFileAlloc(allocator, path, 10 * 1024 * 1024);
279
- const parsed = try std.json.parseFromSlice(StdJsonValue, allocator, data, .{});
280
- const root = parsed.value;
281
-
282
- const spec_val = switch (root) {
283
- .object => |obj| obj.get("struct") orelse return error.NoStructInTestJson,
284
- else => return error.TestJsonNotObject,
285
- };
286
-
287
- return RunPack{
288
- .spec = Spec{ .data = spec_val },
289
- .allocator = allocator,
290
- .file_data = data,
291
- .parsed = parsed,
292
- };
293
- }
294
-
295
- // ---- Corpus matching: matchval / doMatch ----
296
- //
297
- // The primary corpus asserts with `match` as often as with `out`, and its
298
- // error expectations are regexes. runsetAlloc resolved only `in`, had no
299
- // match support and silently skipped any entry carrying `err` — so it could
300
- // drive the struct corpus but not this one. Semantics are the reference's:
301
- // exact equality first, then __UNDEF__/__EXISTS__ markers, then a /regex/, and
302
- // finally a case-insensitive substring.
303
-
304
- fn stringifyAlloc(alloc: Allocator, v: StdJsonValue) []const u8 {
305
- var buf = std.ArrayList(u8).init(alloc);
306
- if (v == .string) return v.string;
307
- std.json.stringify(v, .{}, buf.writer()) catch return "";
308
- return buf.items;
309
- }
310
-
311
- pub fn matchval(alloc: Allocator, check: StdJsonValue, base: StdJsonValue) bool {
312
- if (jsonEqual(check, base)) return true;
313
-
314
- if (check == .string) {
315
- const c = check.string;
316
- if (std.mem.eql(u8, c, UNDEFMARK)) return base == .null;
317
- if (std.mem.eql(u8, c, EXISTSMARK)) return base != .null;
318
-
319
- const basestr = stringifyAlloc(alloc, base);
320
-
321
- // A /pattern/ is a regex over the stringified base.
322
- if (2 <= c.len and c[0] == '/' and c[c.len - 1] == '/') {
323
- const pat = c[1 .. c.len - 1];
324
- // Through the MODULE, never `../utility/voxgigstruct/regex.zig`:
325
- // a file may belong to exactly one module, and regex.zig already
326
- // belongs to voxgig-struct. Importing it by path a second time is
327
- // "file exists in multiple modules".
328
- return voxgig_struct.re_test(pat, basestr);
329
- }
330
-
331
- // Otherwise a case-insensitive substring, as the reference does.
332
- const lc_base = std.ascii.allocLowerString(alloc, basestr) catch return false;
333
- const lc_check = std.ascii.allocLowerString(alloc, c) catch return false;
334
- return std.mem.indexOf(u8, lc_base, lc_check) != null;
335
- }
336
-
337
- return false;
338
- }
339
-
340
- fn getPath(base: StdJsonValue, path: []const []const u8) StdJsonValue {
341
- var cur = base;
342
- for (path) |seg| {
343
- switch (cur) {
344
- .object => |o| cur = o.get(seg) orelse return StdJsonValue{ .null = {} },
345
- .array => |a| {
346
- const idx = std.fmt.parseInt(usize, seg, 10) catch return StdJsonValue{ .null = {} };
347
- if (idx >= a.items.len) return StdJsonValue{ .null = {} };
348
- cur = a.items[idx];
349
- },
350
- else => return StdJsonValue{ .null = {} },
351
- }
352
- }
353
- return cur;
354
- }
355
-
356
- /// Walk `check`; every LEAF must matchval against the same path in `base`.
357
- pub fn doMatch(
358
- alloc: Allocator,
359
- check: StdJsonValue,
360
- base: StdJsonValue,
361
- path: *std.ArrayList([]const u8),
362
- ) !void {
363
- switch (check) {
364
- .object => |o| {
365
- var it = o.iterator();
366
- while (it.next()) |kv| {
367
- try path.append(kv.key_ptr.*);
368
- try doMatch(alloc, kv.value_ptr.*, base, path);
369
- _ = path.pop();
370
- }
371
- },
372
- .array => |a| {
373
- for (a.items, 0..) |item, i| {
374
- const seg = try std.fmt.allocPrint(alloc, "{d}", .{i});
375
- try path.append(seg);
376
- try doMatch(alloc, item, base, path);
377
- _ = path.pop();
378
- }
379
- },
380
- else => {
381
- const baseval = getPath(base, path.items);
382
- if (!matchval(alloc, check, baseval)) {
383
- std.debug.print("\n MATCH: {s}: [{s}] <=> [{s}]\n", .{
384
- joinPath(alloc, path.items),
385
- fmtJson(check),
386
- fmtJson(baseval),
387
- });
388
- return error.MatchMismatch;
389
- }
390
- },
391
- }
392
- }
393
-
394
- fn joinPath(alloc: Allocator, parts: []const []const u8) []const u8 {
395
- return std.mem.join(alloc, ".", parts) catch "?";
396
- }
397
-
398
- // ---- Result comparison (operates on std.json.Value) ----
399
-
400
- fn checkResult(expected: StdJsonValue, result: StdJsonValue) !void {
401
- if (jsonEqual(expected, result)) return;
402
-
403
- if (expected == .string) {
404
- if (std.mem.eql(u8, expected.string, NULLMARK)) {
405
- if (result == .null) return;
406
- }
407
- }
408
-
409
- std.debug.print("\n FAIL: expected {s} got {s}\n", .{
410
- fmtJson(expected),
411
- fmtJson(result),
412
- });
413
- return error.ResultMismatch;
414
- }
415
-
416
- fn fmtJson(val: StdJsonValue) []const u8 {
417
- // Best-effort one-line representation for diagnostic output. Uses the
418
- // process-wide page allocator so the lifetime is OK for a print-and-die.
419
- var buf = std.ArrayList(u8).init(std.heap.page_allocator);
420
- std.json.stringify(val, .{}, buf.writer()) catch return "?";
421
- return buf.items;
422
- }
423
-
424
- /// Deep equality for std.json.Value.
425
- pub fn jsonEqual(a: StdJsonValue, b: StdJsonValue) bool {
426
- const TagType = std.meta.Tag(StdJsonValue);
427
- const tag_a: TagType = a;
428
- const tag_b: TagType = b;
429
-
430
- // Allow integer/float cross-comparison for numeric equality.
431
- if ((tag_a == .integer or tag_a == .float) and (tag_b == .integer or tag_b == .float)) {
432
- const fa: f64 = if (tag_a == .integer) @floatFromInt(a.integer) else a.float;
433
- const fb: f64 = if (tag_b == .integer) @floatFromInt(b.integer) else b.float;
434
- return fa == fb;
435
- }
436
-
437
- if (tag_a != tag_b) return false;
438
-
439
- return switch (a) {
440
- .null => true,
441
- .bool => |av| av == b.bool,
442
- .integer => |av| av == b.integer,
443
- .float => |av| av == b.float,
444
- .string => |av| std.mem.eql(u8, av, b.string),
445
- .number_string => |av| std.mem.eql(u8, av, b.number_string),
446
- .array => |av| {
447
- const bv = b.array;
448
- if (av.items.len != bv.items.len) return false;
449
- for (av.items, bv.items) |ai, bi| {
450
- if (!jsonEqual(ai, bi)) return false;
451
- }
452
- return true;
453
- },
454
- .object => |av| {
455
- const bv = b.object;
456
- if (av.count() != bv.count()) return false;
457
- var it = av.iterator();
458
- while (it.next()) |kv| {
459
- const bval = bv.get(kv.key_ptr.*) orelse return false;
460
- if (!jsonEqual(kv.value_ptr.*, bval)) return false;
461
- }
462
- return true;
463
- },
464
- };
465
- }