Skip to content

test: add `common.mustNotMutateObjectDeep()`

Problem

tl;dr: usually we don't want core methods to have side effects of mutating input values.

Let's imagine function having the following flow inside:

function makeRequest(ipaddr, options) {
  if (typeof options.port === 'number')
    return _mkRq(ipaddr, options);
  switch (options.protocol) {
    case 'ftp': options.port = 21; break;
    case 'http': options.port = 80; break;
    default: // unknown, whatever
  }
  return _mkRq(ipaddr, options);
}

Let's try to use it:

const opts = { headers };
makeRequest(addr, opts); // unknown://addr:unknown --- ok
opts.protocol = 'http';
makeRequest(addr, opts); // http://addr:80 --- got side effects
opts.protocol = 'ftp';
makeRequest(addr, opts); // ftp://addr:80 --- suffered from side effects

To run into such things in tests, we need to perform specific calls in specific order, and it still doesn't guarantee catching. Simple tests like makeRequest(addr, Object.freeze({})) won't help if mutation is conditional.

Solution

This PR adds common.mustNotMutate() which improves our ability to test functions for undesired side effects.

Pass an object into it and use returned value in tests whenever it must remain unchanged:

...
opts.protocol = 'http';
makeRequest(addr, common.mustNotMutate(opts)); // http://addr:80 --- testing for side effects
AssertionError [ERR_ASSERTION]: Expected no side effects, got 80 assigned to port

Or make an immutable "view" on any object:

const mFoo = { bar: 'baz' };
const iFoo = mustNotMutate(mFoo);
mFoo.bar = 'qux'; // affects BOTH mFoo and iFoo
iFoo.bar = 'gwak'; // AssertionError

Or keep mutable "view" and make an object immutable:

const realProcessEnv = process.env;
process.env = mustNotMutate(process.env);
realProcessEnv.LANG = 'en_GB'; // affects BOTH realProcessEnv and process.env
process.env.LANG = 'en_GB'; // AssertionError

Example

[WIP] Using this function in some fs tests: https://github.com/LiviaMedeiros/node/commit/48a8bd155eebe3510f581db95d47c553d4b22add

Merge request reports

Loading