text: // Provides convenience methods for confirming system.profile content.
  
  // Given a command, build its expected shape in the system profiler.
  function buildCommandProfile(command, sharded) {
      let commandProfile = {};
  
      if (sharded && command.mapReduce) {
          // Unlike other read commands, mapReduce is rewritten to a different format when sent to
          // shards if the input collection is sharded, because it is executed in two phases.
          // We do not check for the 'map' and 'reduce' fields, because they are functions, and
          // we cannot compaare functions for equality.
          commandProfile["command.out"] = {$regex: "^tmp.mrs"};
          commandProfile["command.shardedFirstPass"] = true;
      } else if (command.update) {
          // Updates are batched, but only allow using buildCommandProfile() for an update batch that
          // contains a single update, since the profiler generates separate entries for each update
          // in the batch.
          assert(command.updates.length == 1);
          for (let key in command.updates[0]) {
              commandProfile["command." + key] = command.updates[0][key];
          }
          // Though 'upsert' and 'multi' are optional fields, they are written with the default value
          // in the profiler.
          commandProfile["command.upsert"] = commandProfile["command.upsert"] || false;
          commandProfile["command.multi"] = commandProfile["command.multi"] || false;
      } else if (command.delete) {
          // Deletes are batched, but only allow using buildCommandProfile() for a delete batch that
          // contains a single delete, since the profiler generates separate entries for each delete
          // in the batch.
          assert(command.deletes.length == 1);
          for (let key in command.deletes[0]) {
              commandProfile["command." + key] = command.deletes[0][key];
          }
      } else {
          for (let key in command) {
              commandProfile["command." + key] = command[key];
          }
      }
      return commandProfile;
  }
  
  // Retrieve latest system.profile entry.
  function getLatestProfilerEntry(profileDB, filter) {
      if (filter === null) {
          filter = {};
      }
      var cursor = profileDB.system.profile.find(filter).sort({$natural: -1});
      assert(
          cursor.hasNext(),
          "could not find any entries in the profile collection matching filter: " + tojson(filter));
      return cursor.next();
  }
  
  // Returns a string representing the wire protocol used for commands run on the given connection.
  // This string matches the system.profile "protocol" field when commands are profiled.
  function getProfilerProtocolStringForCommand(conn) {
      const protocols = conn.getClientRPCProtocols();
      if ("all" === protocols || /Msg/.test(protocols))
          return "op_msg";
      if (/Query/.test(protocols))
          return "op_query";
      doassert(`Unknown prototocol string ${protocols}`);
  }
  
  /**
   * Throws an assertion if the profiler contains more than 'maxExpectedMatches' entries matching
   * "filter", or if there are no matches. Optional arguments "errorMsgFilter" and "errorMsgProj"
   * limit profiler output if this asserts.
   */
  function profilerHasAtLeastOneAtMostNumMatchingEntriesOrThrow(
      {profileDB, filter, maxExpectedMatches, errorMsgFilter, errorMsgProj}) {
      assert(typeof maxExpectedMatches === 'number' && maxExpectedMatches > 0,
             "'maxExpectedMatches' must be a number > 0");
  
      const numMatches = profileDB.system.profile.find(filter).itcount();
  
      assert.gt(numMatches,
                0,
                "Expected at least 1 op matching: " + tojson(filter) + " in profiler " +
                    tojson(profileDB.system.profile.find(errorMsgFilter, errorMsgProj).toArray()));
  
      assert.lte(numMatches,
                 maxExpectedMatches,
                 "Expected at most " + maxExpectedMatches + " op(s) matching: " + tojson(filter) +
                     " in profiler " +
                     tojson(profileDB.system.profile.find(errorMsgFilter, errorMsgProj).toArray()));
  }
  
  /**
   * Throws an assertion if the profiler does not contain exactly 'numExpectedMatches' entries
   * matching "filter". Optional arguments "errorMsgFilter" and "errorMsgProj" limit profiler output
   * if this asserts.
   */
  function profilerHasNumMatchingEntriesOrThrow(
      {profileDB, filter, numExpectedMatches, errorMsgFilter, errorMsgProj}) {
      assert(typeof numExpectedMatches === 'number' && numExpectedMatches >= 0,
             "'numExpectedMatches' must be a number >= 0");
  
      assert.eq(profileDB.system.profile.find(filter).itcount(),
                numExpectedMatches,
                "Expected exactly " + numExpectedMatches + " op(s) matching: " + tojson(filter) +
                    " in profiler " +
                    tojson(profileDB.system.profile.find(errorMsgFilter, errorMsgProj).toArray()));
  }
  
  /**
   * Throws an assertion if the profiler does not contain any entries matching "filter". Optional
   * arguments "errorMsgFilter" and "errorMsgProj" limit profiler output if this asserts.
   */
  function profilerHasAtLeastOneMatchingEntryOrThrow(
      {profileDB, filter, errorMsgFilter, errorMsgProj}) {
      assert.gte(profileDB.system.profile.find(filter).itcount(),
                 1,
                 "Expected at least 1 op matching: " + tojson(filter) + " in profiler " +
                     tojson(profileDB.system.profile.find(errorMsgFilter, errorMsgProj).toArray()));
  }
  
  /**
   * Throws an assertion if the profiler does not contain exactly one entry matching "filter".
   * Optional arguments "errorMsgFilter" and "errorMsgProj" limit profiler output if this asserts.
   */
  function profilerHasSingleMatchingEntryOrThrow({profileDB, filter, errorMsgFilter, errorMsgProj}) {
      profilerHasNumMatchingEntriesOrThrow({
          profileDB: profileDB,
          filter: filter,
          numExpectedMatches: 1,
          errorMsgFilter: errorMsgFilter,
          errorMsgProj: errorMsgProj
      });
  }
  
  /**
   * Throws an assertion if the profiler contains any entries matching "filter". Optional arguments
   * "errorMsgFilter" and "errorMsgProj" limit profiler output if this asserts.
   */
  function profilerHasZeroMatchingEntriesOrThrow({profileDB, filter, errorMsgFilter, errorMsgProj}) {
      profilerHasNumMatchingEntriesOrThrow({
          profileDB: profileDB,
          filter: filter,
          numExpectedMatches: 0,
          errorMsgFilter: errorMsgFilter,
          errorMsgProj: errorMsgProj
      });
  }
  