private boolean objectsEqual(Object o1, Object o2) {
    // Assumed that o1 and o2 are the same object type as both are from collections created by
    // executing the same query
    if (o1 instanceof Struct) {
      // if o2 is null, an NPE will be thrown.
      Object[] values1 = ((Struct) o1).getFieldValues();
      Object[] values2 = ((Struct) o2).getFieldValues();
      assertEquals(values1.length, values2.length);
      boolean elementEqual = true;
      for (int i = 0; i < values1.length; ++i) {
        elementEqual =
            elementEqual && ((values1[i] == values2[i]) || values1[i].equals(values2[i]));
      }
      return elementEqual;
    } else {
      // if o1 is null and o2 is not, an NPE will be thrown
      return o1 == o2 || o1.equals(o2);
    }
  }
Used by these tests:
<ul>
<li>EquiJoinIntegrationTest</li>
<li>IUMRCompositeIteratorJUnitTest</li>
<li>IUMRMultiIndexesMultiRegionJUnitTest</li>
<li>IUMRShuffleIteratorsJUnitTest</li>
<li>IUMRSingleRegionJUnitTest</li>
<li>IndexCreationJUnitTest</li>
<li>IndexHintJUnitTest</li>
<li>IndexMaintainceJUnitTest</li>
<li>IndexUseJUnitTest</li>
<li>IndexedMergeEquiJoinScenariosJUnitTest</li>
<li>MultiRegionIndexUsageJUnitTest</li>
<li>NonDistinctOrderByPartitionedJUnitTest</li>
<li>NonDistinctOrderByReplicatedJUnitTest</li>
<li>NonDistinctOrderByTestImplementation</li>
<li>OrderByPartitionedJUnitTest</li>
<li>OrderByReplicatedJUnitTest</li>
<li>OrderByTestImplementation</li>
<li>QueryIndexUsingXMLDUnitTest</li>
<li>QueryREUpdateInProgressJUnitTest</li>
<li>QueryUsingFunctionContextDUnitTest</li>
<li>QueryUsingPoolDUnitTest</li>
<li>TestNewFunctionSSorRSIntegrationTest</li>
</ul>
Also used by:
<ul>
<li>GroupByTestImpl</li>
<li>PdxGroupByTestImpl</li>
<li>PRQueryDUnitHelper</li>
</ul>
geode-junit/src/main/java/org/apache/geode/cache/query/functional/StructSetOrResultsSet.java