Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PROC-1219: Fix rule return result check so that it supports method calls #99

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

robertdanci
Copy link

No description provided.

@@ -32,14 +32,6 @@
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jasper-el</artifactId>
</exclusion>
<exclusion>
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proctor-tomcat-deps does not bring in tomcat-jsp-api and neither tomcat-servlet-api.

.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Received non-boolean return value");
// String 'true' is true
assertTrue(ruleEvaluator.evaluateBooleanRule("${'tr'}${'ue'}", emptyMap()));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think this is a valid format, ${'true'} would be valid but I do not think this format should be supported. cc @stevenchen-indeed for confirmation

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes this does not look like convention. If it does not error out, maybe it is a corner case that was not caught before.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, it's okay as I think no one writes the rule like ${'true'}. But this will help validate the custom function like author's team need: placementFilter.matchesMetadata(INDEED_PLUS)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking into this we already allow it to get inputted into a test this just makes parsing it valid. I agree with Van it is okay.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, there was already a test with this rule (which probably should not be allowed on the UI) so I just 'fixed' it here in light of the new approach.

}

for (String rule : ImmutableList.of("${!context.isValid()}", "${context.isFortyTwo('47')}")) {
assertFalse("rule '" + rule + "' should be true for " + context, ruleEvaluator.evaluateBooleanRule(rule, context));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: "' should be false for "

@@ -131,51 +131,26 @@ public boolean evaluateBooleanRule(final String rule, @Nonnull final Map<String,
}

final ELContext elContext = createElContext(values);
final ValueExpression ve = expressionFactory.createValueExpression(elContext, rule, boolean.class);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i tested in local, actually boolean.class still works. ve.getValue(elContext); will return the correct boolean value.
It will fail in checkRuleIsBooleanType, which calls ve.getType, which is removed by your changes.

Therefore is there any other reason that we should change the rule type to String?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason is that we still check the return type (see line 136) and that method now expects a String.
If we are happy with removing the call to checkRuleIsBooleanType we can coerce to boolean instead.

Tbh I don't think there's much value of checking that type is boolean at evaluation time since we already did that when the rule was added on the UI (in RuleVerifyUtils). Was thinking to remove it but we have a test that checks this (TestRuleEvaluator#testNonBooleanShouldFail) and wanted to minimize the changes but happy to do it if we have consensus.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks Robert.
What i found is, if we keep checkRuleIsBooleanType the same, changing to string "final ValueExpression ve = expressionFactory.createValueExpression(elContext, rule, String.class);" will still result in property not found in checkRuleIsBooleanType.
javax.el.PropertyNotFoundException: Property [isValid] not found on type [com.indeed.proctor.common.TestRuleEvaluator$Temp]
There i am not sure what's the difference between String and boolean in this case.

At least that's what i saw when i run from unit tests. Do you see different behavior?

Or do you mean Class<?> type = ve.getType(elContext); may not be required, using string and check "true" or "false" is just as reliable?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, changing the coerce type in expressionFactory.createValueExpression(elContext, rule, boolean.class); from boolean to String is not sufficient to avoid the error, that's why I've changed checkRuleIsBooleanType method to no longer call getType and I'm doing the check based upon the string result.

Above I was questioning if we should call checkRuleIsBooleanType at all as part of RuleEvaluator#evaluateBooleanRule method because we should have already done so when the rule added on the UI (see RuleVerifyUtils#verifyRule). We can keep it if we want an extra check or we can simplify to:

  final ValueExpression ve = expressionFactory.createValueExpression(elContext, rule, boolean.class);
  return (boolean) ve.getValue(elContext);

in RuleEvaluator#evaluateBooleanRule and remove the tests that use invalid rules (TestRuleEvaluator#testNonBooleanShouldFail). This is just an alternative, we can leave things as in the PR in interest of time since this is just an optimization.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest i am also trying to learn how does the proctor api validate the rule.
Taking your unit tests for example,

final Map<String, Object> context = ImmutableMap.of("context", new Temp());

The Temp can be any class that you need in your application. How does Proctor Api get access to those custom class?

@zacharygoodwin zacharygoodwin self-requested a review April 12, 2023 20:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants