Proposal - Amend Test Specification / Error Handling #20
Replies: 10 comments 43 replies
-
Something to think about before I undraft this: The following rule gives me pause, and we could decide to avoid these cases, { "*": ["h", 5] } This guy would emit Should errors be expected to halt / prevent logic execution? I would think so, and if so, I think that helps us set guidelines for what error boundaries we want to test for. |
Beta Was this translation helpful? Give feedback.
-
Some excerpts from another dicussion over JSON Logic error behaviors. From @gregsdennis
From @dslmeinte
From me
We need to decide if JSON Logic will support the concept of "Soft Errors" which doesn't halt execution and instead emit some value, or if errors will exclusively halt termination. I can see arguments both ways on numeric conversion. How do we handle It'd be a bit messy if we allowed |
Beta Was this translation helpful? Give feedback.
-
I have an idea I'll tinker with this weekend w/r/t "soft errors", and how to make them viable across implementations. I'm personally not really leaning heavily towards either approach. I believe deciding everything is a Hard Error would be much simpler from a specification perspective, but potentially reduces capability / efficiency from an AST perspective. -- Keep in mind that this is half-baked and I'm merely playing with the idea for soft-errors to see if there's any viability in this. Right now, the idea I'm contemplating is some sort of engine.addMethod('error', ([type]) => {
// Implementations could choose to substitute values that make sense
if (type === 'NaN') return Number.NaN
// literally returns an object;
// it could be best if this was some stable reference for easier comparison, rather than a new
// object each time.
return { error: type }
}) And to check for this soft error, which is actually a data value, one could do: [
{
"description": "Checks if 0 / 0 produces NaN",
"rule": { "/": [0, 0] },
"result": { "error": "NaN" },
"data": null
},
{
"description": "Adding 1 to NaN",
"rule": { "+": [1, { "error": "NaN" }] },
"result": { "error": "NaN" },
"data": null
}
] In this case, there'd be an equivalence established in the test runner between Implementations / Architectures without a native NaN concept would have to pass the JSON Object around. There is a question of truthiness, in JS, On the surface, it seems like this could be alright, but what happens when I pass in a context with: {
"x": { "error": "NaN" }
} And call Could this ever lead to unintended behavior, or work in unintuitive ways? There are mental models where I could see this working out fine.. but also ones where this could cause problems. |
Beta Was this translation helpful? Give feedback.
-
@JTeeuwissen said:
(Funnily enough, I actually commited an experiment on that shortly before: json-logic/json-logic-engine@5d5c38d) |
Beta Was this translation helpful? Give feedback.
-
So I've been experimenting with the soft-error construct and... it's actually seemingly decent. It's OK. I think there's an argument for soft-error viability. What I've implemented:
The coalescing allows us to do something like { "try": [{ "+": [{ "val": "x" }, 1]}, 42] } // Falls back to 42 if val x cannot coerce to a number
|
Beta Was this translation helpful? Give feedback.
-
Before it is snowed under in a comment section, I propose a somewhat different approach: For the testing data
Where each rule either returns a result, or an error, to be delivered in a language fitting manner (exceptions, monads, etc.) The difference between data and error implies that they are handled differently from each other, error not simply being data in a special format (which would not play nice with operators using objects as input). |
Beta Was this translation helpful? Give feedback.
-
At this phase, it appears that sentiment is leaning towards soft errors. I'm going to leave this open for a bit longer to offer folks time to vote on each. (You can vote independently on each solution, and it's okay to be comfortable with both!) |
Beta Was this translation helpful? Give feedback.
-
At this point, I'm going to revise the root proposal in favor of soft errors, but if there ends up being more support for hard errors, I can adjust accordingly. |
Beta Was this translation helpful? Give feedback.
-
I'm voting +1 on Option A, +0.5 on Option B. |
Beta Was this translation helpful? Give feedback.
-
Current Votes:
Needs one more approval for "A" to go through, @codetiger are you on board with A? |
Beta Was this translation helpful? Give feedback.
-
Background
We currently have a test specification format here: https://github.com/json-logic/.github/blob/main/TEST_FORMAT.md
This is great for positive testing; but we might want to amend our specification to make things simple for negative testing, as well.
Positive Testing - Checking that functionality behaves as expected.
Negative Testing - Checking that functionality fails as expected.
Proposal
I'd like to amend the test format to essentially be:
Essentially, every rule has:
But the rule must have either:
or
But not both.
This would potentially allow us to define a test case like:
I'm going to do something dumb, and propose two options. Please vote on each independently.
**Option A (Hard Errors / Exceptions)**
With this proposal, we will define that errors should bubble up the AST and halt execution.
Implementations will be responsible for deciding how they want to emit and represent hard errors.
With this proposal, we will introduce a few operators:
throw
try
{ "type": "type" }
Test Cases
throw
Expand
try
Expand
**Option B (Soft Errors)** -- (Withdrawn)
This option has been withdrawn.
With this proposal, we will recognize two forms of errors:
error
. These errors can be handled in the AST. (NaN
is an example of a Soft Error)For soft errors, implementations may choose to create equivalence classes, to define a language construct as being equal to a soft error. (
NaN
can be made equivalent to{ "error": "NaN" }
)Implementations will be responsible for deciding how they want to emit and represent hard errors.
With this proposal, we will introduce a few operators:
error
Implementations may choose to substitute the return value for an equivalent language construct, as long as it's handled the exact same way.
try
??
andor
with short-circuit behavior. It will coalesce to the first non-error argument, or it will panic.**(Do we want this to return the last argument instead? If so, I'll reintroduce
panic
)Test Cases
error
Expand
try
Expand
Related Materials
For Option A:
An example of how the numeric tests would work. They cause an error.
For Option B:
Additional Decisions (Both Proposals)
NaN
is an Error. In Option A, this is a Hard Error. In Option B, this is a Soft Error.NaN
Beta Was this translation helpful? Give feedback.
All reactions