text: // $substr returns an empty string if the position argument is out of bounds.  SERVER-6186
  
  t = db.jstests_aggregation_server6186;
  t.drop();
  
  t.save({});
  
  function substr(string, pos, n) {
      return t.aggregate({$project: {a: {$substr: [string, pos, n]}}}).toArray()[0].a;
  }
  
  function expectedSubstr(string, pos, n) {
      if (pos < 0) {
          // A negative value is interpreted as a large unsigned int, and is expected to be out of
          // bounds.
          return "";
      }
      if (n < 0) {
          // A negative value is interpreted as a large unsigned int, expected to exceed the length
          // of the string.  Passing the string length is functionally equivalent.
          n = string.length;
      }
      return string.substring(pos, pos + n);
  }
  
  function assertSubstr(string, pos, n) {
      assert.eq(expectedSubstr(string, pos, n), substr(string, pos, n));
  }
  
  function checkVariousSubstrings(string) {
      for (pos = -2; pos < 5; ++pos) {
          for (n = -2; n < 7; ++n) {
              assertSubstr(string, pos, n);
          }
      }
  }
  
  checkVariousSubstrings("abc");
  checkVariousSubstrings("");
  