text: // Tests that a transaction expires and is then aborted by the server. Uses the server parameter
  // 'transactionLifetimeLimitSeconds' to lower the transaction lifetime for quicker transaction
  // expiration. This is the mongos version for: jstests/core/txns/abort_expired_transaction.js.
  //
  // @tags: [uses_transactions, uses_multi_shard_transaction]
  
  (function() {
  "use strict";
  
  let st = new ShardingTest({shards: 2});
  
  assert.commandWorked(st.s.adminCommand({enableSharding: 'test'}));
  st.ensurePrimaryShard('test', st.shard0.name);
  assert.commandWorked(st.s.adminCommand({shardCollection: 'test.user', key: {x: 1}}));
  assert.commandWorked(st.s.adminCommand({split: 'test.user', middle: {x: 0}}));
  assert.commandWorked(st.s.adminCommand({moveChunk: 'test.user', find: {x: 0}, to: st.shard1.name}));
  
  let lowerTxnTimeout = (conn) => {
      assert.commandWorked(
          conn.getDB('admin').runCommand({setParameter: 1, transactionLifetimeLimitSeconds: 1}));
  };
  
  st.rs0.nodes.forEach(lowerTxnTimeout);
  st.rs1.nodes.forEach(lowerTxnTimeout);
  
  let testDB = st.s.getDB('test');
  
  // Create the collections in the shards outside the transactions.
  assert.commandWorked(testDB.runCommand(
      {insert: 'user', documents: [{x: -1}, {x: 1}], writeConcern: {w: 'majority'}}));
  
  const session = st.s.startSession();
  const sessionDb = session.getDatabase('test');
  
  let txnNumber = 0;
  
  assert.commandWorked(sessionDb.runCommand({
      insert: 'user',
      documents: [{x: -10}, {x: 10}],
      txnNumber: NumberLong(txnNumber),
      startTransaction: true,
      autocommit: false,
  }));
  
  // We can deterministically wait for the transaction to be aborted by waiting for currentOp
  // to cease reporting the inactive transaction: the transaction should disappear from the
  // currentOp results once aborted.
  assert.soon(
      function() {
          const sessionFilter = {
              active: false,
              opid: {$exists: false},
              desc: "inactive transaction",
              "transaction.parameters.txnNumber": NumberLong(txnNumber),
              "lsid.id": session.getSessionId().id
          };
  
          const priConn = st.rs0.getPrimary();
          const res = priConn.getDB("admin").aggregate(
              [{$currentOp: {allUsers: true, idleSessions: true}}, {$match: sessionFilter}]);
  
          return (res.itcount() == 0);
      },
      "currentOp reports that the idle transaction still exists, it has not been " +
          "aborted as expected.");
  
  assert.commandFailedWithCode(sessionDb.runCommand({
      insert: 'user',
      documents: [{x: -100}, {x: 100}],
      txnNumber: NumberLong(txnNumber),
      autocommit: false,
  }),
                               ErrorCodes.NoSuchTransaction);
  
  session.endSession();
  
  st.stop();
  }());
  