kabo87777 opened a new pull request, #16688:
URL: https://github.com/apache/iotdb/pull/16688

   # Fix Non-Deterministic Behavior in AlignedByDeviceTest
   
   ## Problem
   
   Nine tests in `AlignedByDeviceTest` were failing non-deterministically under 
NonDex (50-100% failure rates) due to order-dependent fragment assertions:
   
   - `testAggregation2Device2Region`
   - `testAggregation2Device2RegionOrderByTime`
   - `testAggregation2Device2RegionWithValueFilter`
   - `testAggregation2Device2RegionWithValueFilterOrderByTime`
   - `testAggregation2Device3RegionWithValueFilter`
   - `testAggregation2Device3RegionWithValueFilterOrderByTime`
   - `testDiffFunction2Device2Region`
   - `testDiffFunction2Device3Region`
   - `testDiffFunctionWithOrderByTime2Device3Region`
   
   ## Way to Reproduce
   
   ```bash
   cd iotdb-core/datanode
   mvn edu.illinois:nondex-maven-plugin:2.1.1:nondex \
     -Dtest=AlignedByDeviceTest#testAggregation2Device2Region \
     -DnondexRuns=10 -Drat.skip=true
   # Result: 10/10 failures (100% failure rate before fix)
   ```
   
   ## Root Cause
   
   Tests used fixed-index access to fragments (`plan.getInstances().get(0)`) 
assuming deterministic order:
   
   ```java
   PlanNode f1Root = plan.getInstances().get(0).getFragment().getPlanNodeTree();
   PlanNode f2Root = plan.getInstances().get(1).getFragment().getPlanNodeTree();
   assertTrue(f1Root.getChildren().get(0) instanceof AggregationMergeSortNode); 
// Fails when order changes
   ```
   
   Fragment order is non-deterministic due to HashMap iteration during 
distributed query planning. When NonDex shuffled collection order, fragments 
appeared at different positions, causing assertions to fail even though the 
query plan was semantically correct.
   
   ## Solution
   
   Made assertions **order-independent** by counting node types across all 
fragments instead of assuming fixed positions.
   
   ### Added Helper Methods
   ```java
   private int countNodesOfType(PlanNode root, Class<?> nodeType) {
     // Recursively counts nodes of a specific type in plan tree
   }
   
   private <T extends PlanNode> T findFirstNodeOfType(PlanNode root, Class<T> 
nodeType) {
     // Recursively finds first node of a specific type in plan tree
   }
   ```
   
   ### Transformed Assertions
   
   **Before (Order-Dependent):**
   ```java
   PlanNode f1Root = plan.getInstances().get(0).getFragment().getPlanNodeTree();
   assertTrue(f1Root.getChildren().get(0) instanceof AggregationMergeSortNode);
   assertTrue(f1Root.getChildren().get(0).getChildren().get(0) instanceof 
DeviceViewNode);
   ```
   
   **After (Order-Independent):**
   ```java
   int aggMergeSortCount = 0;
   int deviceViewCount = 0;
   for (FragmentInstance instance : plan.getInstances()) {
     PlanNode root = instance.getFragment().getPlanNodeTree();
     aggMergeSortCount += countNodesOfType(root, 
AggregationMergeSortNode.class);
     deviceViewCount += countNodesOfType(root, DeviceViewNode.class);
   }
   assertTrue("Expected at least one AggregationMergeSortNode", 
aggMergeSortCount >= 1);
   assertTrue("Expected at least two DeviceViewNodes", deviceViewCount >= 2);
   ```
   
   ### Key Improvements
   - Replaced fixed-index access with iteration through all fragments
   - Changed strict equality to flexible assertions (`>= N` instead of exact 
position checks)
   - Added descriptive assertion messages for debugging
   - Recursive tree traversal searches entire plan trees regardless of node 
depth or position
   
   ## Key Changed Classes
   
   - **AlignedByDeviceTest**: Added 2 helper methods, modified 9 test methods 
(~400 lines), test-only changes


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to