karma-runner / karma-runner/karma
Javascript Heap out of memory when Karma serving files
- Dominant language
- JavaScript
- Stars
- 12k
- Forks
- 1.7k
- PR merge metrics
- No merged PRs in 30d
Description
### Expected behaviour
Single run tests runs consistently and watch mode can recompile consistently
### Actual behaviour
Node crashes because of the heap running out of memory when just serving a few dozen files.
### Environment Details
OS: Mac OS Sierra 10.12.4
Node: 6.9.5
"karma": "^1.6.0",
"karma-chai": "^0.1.0",
"karma-chrome-launcher": "^2.0.0",
"karma-cli": "^1.0.1",
"karma-mocha": "^1.3.0",
"karma-mocha-reporter": "^2.2.3",
"karma-phantomjs-launcher": "^1.0.4",
"karma-sinon-chai": "git://github.com/kmees/karma-sinon-chai#bca7e7a2d6e90d4c7c6a6884550c2b3228596d23",
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^2.0.3",
"mocha": "^3.2.0",
"webpack": "^1.12.14",
"webpack-dev-server": "^1.14.1"
- Karma version (output of `karma --version`): 1.6.0
- Relevant part of your `karma.config.js` file
karma.config.js
```javascript
// modify the config for testing
var webpackProdConfig = require('../js/webpack.config.js');
var webpackTestConfig = _.mergeWith({}, webpackProdConfig, {
// use cheaper source maps
devtool: '#cheap-module-inline-source-map',
resolve: {
alias: {
// resolve the test directory
test: __dirname,
// need to use local jquery
jquery: jslibpath('jquery-1.9.1/jquery.js'),
},
// add the test directory path to the root for resolving
root: [__dirname]
}
},
// Use function to make sure arrays are merged by unique values
function (objValue, srcValue) {
if (_.isArray(objValue)) {
return _.union(objValue, srcValue);
}
});
// delete the external jquery
delete webpackTestConfig.externals.jquery;
// delete the entry, karma takes care of this
delete webpackTestConfig.entry;
// delete the output, karma takes care of this
delete webpackTestConfig.output;
module.exports = function(config) {
config.set({
// base path that will be used to resolve all patterns (eg. files, exclude)
basePath: '../..',
plugins: [
'karma-mocha',
'karma-webpack',
'karma-chrome-launcher',
'karma-phantomjs-launcher',
'karma-sinon-chai',
'karma-mocha-reporter',
'karma-sourcemap-loader'
],
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha', 'sinon-chai'],
// list of files / patterns to load in the browser
files: [
'htdocs/test/**/*test.js'
],
// list of files to exclude
exclude: [
],
// preprocess matching files before serving them to the browser
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'htdocs/test/**/*.js': ['webpack']
},
webpack: webpackTestConfig,
// This is a better webpack config than the one below because it outputs
// errors.
webpackMiddleware: {
progress: true,
stats: true,
debug: true,
noInfo: false,
silent: false
},
/*
webpackMiddleware: {
progress: false,
stats: false,
debug: false,
noInfo: true,
silent: true
},
*/
client: {
mocha: {
// change Karma's debug.html to the mocha web reporter
reporter: ['html'],
// Use 'HTML' when running in chrome
//reporter: 'HTML',
timeout: 30000
}
},
// reporter options
mochaReporter: {
showDiff: true
},
// test results reporter to use
// possible values: 'dots', 'progress'
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['mocha'],
// enable / disable colors in the output (reporters and logs)
colors: true,
// level of logging
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
logLevel: config.LOG_INFO || config.LOG_DEBUG,
// enable / disable watching file and executing tests whenever any file changes
autoWatch: false,
// start these browsers
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: ['PhantomJS'],
// Continuous Integration mode
// if true, Karma captures browsers, runs the tests and exits
singleRun: true,
/*
browsers: ['Chrome'],
singleRun: false,
*/
// Concurrency level
// how many browser should be started simultaneous
concurrency: Infinity,
// 10 seconds (the default) isn't long enough. Give phantomjs 60 seconds to
// start up.
browserNoActivityTimeout: 0,
});
};
```
### Steps to reproduce the behaviour
This does not happen consistently in single run mode but virtually every time when watching. The problem presents itself after the compilation is complete and karma is serving the files. Happens in bother Phantomjs and Chrome. Judging from the stack trace provided by node, it seems like a buffer on a stream may be getting too large. The heap getting to about 1.259 GB for just a few dozen files. I have seen the same issue with using webpack 2+; I downgraded to see if that would resolve the issue and it did not. The problematic code seems to be in the karma middleware.

Contributor guide
Research direction
Start with the supplied karma.config.js and reproduce the failure in watch mode using the listed Karma, webpack, Chrome, and PhantomJS setup. Trace the Karma middleware while it serves the compiled files, focusing on the reported stream buffering and heap growth; done means single runs and watch recompilation remain stable without Node exhausting its heap.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js, webpack
- Domain
- testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100