Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix(ngMock): prevent memory leak due to data attached to $rootElement #14098

Closed

Conversation

gkalpak
Copy link
Member

@gkalpak gkalpak commented Feb 20, 2016

Starting with 88bb551, ngMock will attach the $injector to the $rootElement, but will never clean it up, resulting in a memory leak. Since a new $rootElement is created for every test, this leak causes Karma to crash on large test-suites.
The problem was not detected by our internal tests, because we do our own clean-up in
testabilityPatch.js.

This commit prevents the memory leak, by cleaning up all data attached to $rootElement after each test.

Fixes #14094

describe('make sure that we can create an injector outside of tests', function() {
//since some libraries create custom injectors outside of tests,
//we want to make sure that this is not breaking the internals of
//how we manage annotated function cleanup during tests. See #10967
angular.injector([function($injector) {}]);
});


describe('don\'t leak memory between tests', function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer describe block descriptions to be nouns of things that are being tested...

But I see you are following the pattern above :-(

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the descriptions either. I'll tweak them.

@petebacondarwin
Copy link
Contributor

So the idea of the tests is that you have to run a test beforehand that sets up the spies so that you can check to see that the root element was in fact cleaned up?
I think that the wording of the describe and it blocks could be tweaked so that we remember what they are doing in 12 months time.

});
});

describe('don\'t leak memory between tests with mocked `$rootScope`', function() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be "with mocked $rootElement"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup :)

@gkalpak gkalpak force-pushed the fix-ngMock-prevent-memory-leak branch from 44684c9 to 393f68b Compare February 21, 2016 20:51
Starting with 88bb551, `ngMock` will attach the `$injector` to the `$rootElement`, but will never
clean it up, resulting in a memory leak. Since a new `$rootElement` is created for every test,
this leak causes Karma to crash on large test-suites.
The problem was not detected by our internal tests, because we do our own clean-up in
`testabilityPatch.js`.

This commit prevents the memory leak, by cleaning up all data attached to `$rootElement` after each
test.

Fixes angular#14094
@gkalpak gkalpak force-pushed the fix-ngMock-prevent-memory-leak branch from 393f68b to 739d4c6 Compare February 21, 2016 20:58
@gkalpak
Copy link
Member Author

gkalpak commented Feb 21, 2016

I has to rebase this on top of master (because the commit this is supposed to fix was reverted).

I incorporated the original commit (attaching $injector to $rootScope) in this PR's 1st commit. (Other than that, I haven't done any other changes in the 1st commit, so you don't have to re-review the other parts.)

I added a 2nd commit, that addressed your feedback (except for #14098 (comment) - I'll play with that next).
I tried to make the test descriptions as clear as possible and add comments explaining parts of the test logic that felt unclear, but I'm open to suggestions for better explanations 😃

@gkalpak gkalpak force-pushed the fix-ngMock-prevent-memory-leak branch 2 times, most recently from fd1891d to a33e753 Compare February 21, 2016 21:46
- Group into a `describe` block
- Tweak test descriptions
- Fix typos
@gkalpak gkalpak force-pushed the fix-ngMock-prevent-memory-leak branch from a33e753 to b972a12 Compare February 21, 2016 21:48
@gkalpak
Copy link
Member Author

gkalpak commented Feb 21, 2016

I added a 3rd commit that uses jqLite.cleanData(...).

@gkalpak gkalpak force-pushed the fix-ngMock-prevent-memory-leak branch from 9e62160 to d8fca15 Compare February 22, 2016 08:11
@gkalpak
Copy link
Member Author

gkalpak commented Feb 22, 2016

And a 4th commit (fixup 3) that fixes a couple of corner cases.
(BTW, the commit messages contain more details about the contents of each fixup commit.)

- Unify the clean-up paths for tests with/without jQuery, using `angular.element.cleanData()`.
- Remove redundant calls to `.off().removeData()`.
- Fix bug in `testabilityPatch.js`, where `cleanData()` was called with an array of jqLite/jQuery
  elements (instead of "raw" nodes).
@gkalpak gkalpak force-pushed the fix-ngMock-prevent-memory-leak branch from 339468f to 352e2a9 Compare February 22, 2016 10:03
- Reset `originalRootElement` for each test to avoid.
- Fix clean-up break, if `$rootElement` was never initialized.
- Fix clean-up break, if decorated `$rootElement` was falsy (e.g. `null`).
- (Rename `cleanUpElems` to `cleanUpNodes` - since it's "raw" nodes, not jq-wrapped elements.)
@gkalpak gkalpak force-pushed the fix-ngMock-prevent-memory-leak branch 2 times, most recently from 223fb52 to db92324 Compare February 22, 2016 11:21
@petebacondarwin
Copy link
Contributor

LGTM - please squash and merge.

@gkalpak gkalpak closed this in 85ef70f Feb 22, 2016
gkalpak added a commit that referenced this pull request Feb 22, 2016
Starting with 88bb551, `ngMock` will attach the `$injector` to the `$rootElement`, but will never
clean it up, resulting in a memory leak. Since a new `$rootElement` is created for every test,
this leak causes Karma to crash on large test-suites.
The problem was not detected by our internal tests, because we do our own clean-up in
`testabilityPatch.js`.

88bb551 was revert with 1b8590a.
This commit incorporates the changes from 88bb551 and prevents the memory leak, by cleaning up all
data attached to `$rootElement` after each test.

Fixes #14094

Closes #14098
gkalpak added a commit that referenced this pull request Feb 22, 2016
Starting with 88bb551, `ngMock` will attach the `$injector` to the `$rootElement`, but will never
clean it up, resulting in a memory leak. Since a new `$rootElement` is created for every test,
this leak causes Karma to crash on large test-suites.
The problem was not detected by our internal tests, because we do our own clean-up in
`testabilityPatch.js`.

88bb551 was revert with 1b8590a.
This commit incorporates the changes from 88bb551 and prevents the memory leak, by cleaning up all
data attached to `$rootElement` after each test.

Fixes #14094

Closes #14098
@gkalpak
Copy link
Member Author

gkalpak commented Feb 22, 2016

Backported to v1.5.x (75373dd) and v1.4.x (571e323).
(For v.1.4.x I had to also backport jqLiteCleanData() from 96288d0.)

@gkalpak gkalpak deleted the fix-ngMock-prevent-memory-leak branch February 22, 2016 19:57
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants