Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-94786

Fix results comparison in plan_cache_stochastic_test.js

    • Query Execution
    • Fully Compatible
    • ALL
    • 0

      The test `jstests/core/query/plan_cache/plan_cache_stochastic_test.js` runs pseudo-randomly created aggregation queries with and without the plan cache multiple and then compares the query results.

      Query results from multiple runs are supposed to be identical. The test verifies that by first normalizing the results and then comparing them for equality.

      The function `deepSortObjAndArr` in the test normalizes the query results before comparison. 

      However, it does not handle BSON values well. For example, all NumberLong values are turned into an empty document (`{ }`) by this code fragment:

      function deepSortObjAndArr(ent) {
          if (Array.isArray(ent)) {
             ...
          } else if (typeof ent === 'object' && ent !== null) {
              const sortedObj = {};
              Object.keys(ent).sort().forEach(key => {
                sortedObj[key] = deepSortObjAndArr(ent[key]);
              });
              return sortedObj;
          }
          ...
      

      BSON NumberLongs will be turned into `{}` by this function. BSON NumberInts will be converted to plain JavaScript Number values correctly.

      Comparing NumberLong(0) == NumberInt(0) should result in true, but currently it will result in false due to the faulty conversion.

      The test produces queries that can non-deterministically return NumberLong or NumberInt values, depending on in which order results are processed in the query.

      For example, we have found a case in which the test generated a pipeline in which 2 adjacent group operations were ran:

      { "$group" : { "_id" : "$obj17", "lit04" : { "$sum" : "$obj17" }, "lit02" : { "$sum" : "$key01" },  obj16" : { "$sum" : "$lit15" } } },
      { "$group" : { "_id" : "$obj16", "lit13" :{ "$min" : "$lit04" }, "key01" : { "$sum" : "$lit05" } } }
      

      The $group stage can use a hash table based aggregation in the background in SBE, so it is not guaranteed in which order it will return its results.

      In this particular example, the first group stage produces results with a non-determinstic order (due to using a hash table), which are then fed into the second group stage. The $min accumulator then either returned NumberInt(0) or NumberLong(0) as its result. Both are valid, and both should be treated identical.

      However, when the test normalized the query results, it turned NumberLong(0) into {}, so it compared unequal to Number(0), which result in false-positive test failures.

      The normalization function in the test take different BSON Number types into account to handle such minor result differences gracefully.

            Assignee:
            jan.steemann@mongodb.com Jan Steemann
            Reporter:
            jan.steemann@mongodb.com Jan Steemann
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: