Skip to content

Rules : Fix logical operation for negative matchers with multiple values#1147

Merged
PravinPK merged 1 commit intoadobe:dev-v5.5.1from
PravinPK:rulesFix
Jun 11, 2025
Merged

Rules : Fix logical operation for negative matchers with multiple values#1147
PravinPK merged 1 commit intoadobe:dev-v5.5.1from
PravinPK:rulesFix

Conversation

@PravinPK
Copy link
Copy Markdown
Contributor

@PravinPK PravinPK commented Jun 6, 2025

Problem

When processing multiple values, the rules engine used OR logic for all matchers , which creates a logical flaw for negative
conditions. For example

carriername != "AT&T" OR  carriername != "Verizon" OR carriername != "Cricket"

This is always true for negative matchers! If carriername = "AT&T", the condition carriername != "Verizon" makes the entire OR expression true, causing incorrect rule firing.

Impact

This was causing rules to fire when they shouldn't. (Customer issue : IAM was fired too often)

Solution

Modified JSONRulesParser.swift to use AND logic for negative matchers like notContains (nc) and notExists (ne).

Correct evaluation

carriername != "AT&T" AND carriername != "Verizon" AND carriername != "Cricket"

@PravinPK PravinPK requested review from rymorale and sbenedicadb June 6, 2025 23:54
Copy link
Copy Markdown
Member

@sbenedicadb sbenedicadb left a comment

Choose a reason for hiding this comment

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

looks good pending adding another test or two

Comment on lines +192 to +216
// Matcher: ne
func testMatcherNe_multipleValues() {
/// Given:
resetRulesEngine(withNewRules: "rules_testMatcherNe_multipleValues")

mockRuntime.simulateSharedState(for: "com.adobe.module.lifecycle", data: (value: ["lifecyclecontextdata": ["carriername": "AT&T"]], status: .set))
/// When:
rulesEngine.process(event: defaultEvent)
/// Then:
XCTAssertEqual(0, mockRuntime.dispatchedEvents.count)

/// When:
mockRuntime.simulateSharedState(for: "com.adobe.module.lifecycle", data: (value: ["lifecyclecontextdata": ["carriername": "Blue"]], status: .set))
rulesEngine.process(event: defaultEvent)
/// Then:
XCTAssertEqual(1, mockRuntime.dispatchedEvents.count)
let consequenceEvent = mockRuntime.dispatchedEvents[0]
XCTAssertEqual(EventType.rulesEngine, consequenceEvent.type)
XCTAssertEqual(EventSource.responseContent, consequenceEvent.source)
guard let data = consequenceEvent.data?["triggeredconsequence"], let dataWithType = data as? [String: Any] else {
XCTFail()
return
}
XCTAssertEqual("pb", dataWithType["type"] as! String)
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

do we already have this same test where we simulate for one of the values in the list and assert that there are no dispatched consequence events?

Copy link
Copy Markdown
Contributor Author

@PravinPK PravinPK Jun 10, 2025

Choose a reason for hiding this comment

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

Hey Steve, yes we had a test for that case already

"matcher": "ne",
"values": [
"AT&T"
]

Its following tests evaluates ne matchers both positive and negative cases with single value

func testMatcherNe() {
/// Given:
resetRulesEngine(withNewRules: "rules_testMatcherNe")
mockRuntime.simulateSharedState(for: "com.adobe.module.lifecycle", data: (value: ["lifecyclecontextdata": ["carriername": "AT&T"]], status: .set))
/// When:
rulesEngine.process(event: defaultEvent)
/// Then:
XCTAssertEqual(0, mockRuntime.dispatchedEvents.count)
/// When:
mockRuntime.simulateSharedState(for: "com.adobe.module.lifecycle", data: (value: ["lifecyclecontextdata": ["carriername": "Verizon"]], status: .set))
rulesEngine.process(event: defaultEvent)
/// Then:
XCTAssertEqual(1, mockRuntime.dispatchedEvents.count)
let consequenceEvent = mockRuntime.dispatchedEvents[0]
XCTAssertEqual(EventType.rulesEngine, consequenceEvent.type)
XCTAssertEqual(EventSource.responseContent, consequenceEvent.source)
guard let data = consequenceEvent.data?["triggeredconsequence"], let dataWithType = data as? [String: Any] else {
XCTFail()
return
}
XCTAssertEqual("pb", dataWithType["type"] as! String)
}

@PravinPK PravinPK merged commit cc28433 into adobe:dev-v5.5.1 Jun 11, 2025
17 checks passed
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.

2 participants