Skip to content
Browse files

Tests for memory leaks

Conflicts:

	Makefile
  • Loading branch information...
1 parent e4dd8dc commit e63c7821d5fc4e2f92c0606ab16b7846893ac3d1 @isaacs isaacs committed May 3, 2012
View
1 .gitignore
@@ -41,3 +41,4 @@ ipch/
email.md
blog.html
deps/v8-*
+node_modules
View
18 Makefile
@@ -42,14 +42,16 @@ uninstall:
clean:
-rm -rf out/Makefile node node_g out/$(BUILDTYPE)/node blog.html email.md
-find out/ -name '*.o' -o -name '*.a' | xargs rm -rf
+ -rm -rf node_modules
distclean:
-rm -rf out
-rm -f config.gypi
-rm -f config.mk
-rm -rf node node_g blog.html email.md
+ -rm -rf node_modules
-test: all
+test: all node_modules/weak
$(PYTHON) tools/test.py --mode=release simple message
PYTHONPATH=tools/closure_linter/ $(PYTHON) tools/closure_linter/closure_linter/gjslint.py --unix_mode --strict --nojsdoc -r lib/ -r src/ --exclude_files lib/punycode.js
@@ -59,9 +61,17 @@ test-http1: all
test-valgrind: all
$(PYTHON) tools/test.py --mode=release --valgrind simple message
-test-all: all
- python tools/test.py --mode=debug,release
- $(MAKE) test-npm
+node_modules/weak:
+ @if [ ! -f node ]; then make all; fi
+ @if [ ! -d node_modules ]; then mkdir -p node_modules; fi
+ ./node deps/npm/bin/npm-cli.js install weak --prefix="$(shell pwd)"
+
+test-gc: all node_modules/weak
+ $(PYTHON) tools/test.py --mode=release gc
+
+test-all: all node_modules/weak
+ $(PYTHON) tools/test.py --mode=debug,release
+ make test-npm
test-all-http1: all
$(PYTHON) tools/test.py --mode=debug,release --use-http1
View
61 test/gc/test-http-client-connaborted.js
@@ -0,0 +1,61 @@
+// just like test/gc/http-client.js,
+// but aborting every connection that comes in.
+
+function serverHandler(req, res) {
+ res.connection.destroy();
+}
+
+var http = require('http'),
+ weak = require('weak'),
+ done = 0,
+ count = 0,
+ countGC = 0,
+ todo = 18,
+ common = require('../common.js'),
+ assert = require('assert'),
+ PORT = common.PORT;
+
+console.log('We should do '+ todo +' requests');
+
+var http = require('http');
+var server = http.createServer(serverHandler);
+server.listen(PORT, getall);
+
+function getall() {
+ for (var i = 0; i < todo; i++) {
+ (function(){
+ function cb(res) {
+ done+=1;
+ statusLater();
+ }
+
+ var req = http.get({
+ hostname: 'localhost',
+ pathname: '/',
+ port: PORT
+ }, cb).on('error', cb);
+
+ count++;
+ weak(req, afterGC);
+ })()
+ }
+}
+
+function afterGC(){
+ countGC ++;
+}
+
+function statusLater() {
+ setTimeout(status, 1);
+}
+
+function status() {
+ gc();
+ console.log('Done: %d/%d', done, todo);
+ console.log('Collected: %d/%d', countGC, count);
+ if (done === todo) {
+ console.log('All should be collected now.');
+ assert(count === countGC);
+ process.exit(0);
+ }
+}
View
66 test/gc/test-http-client-onerror.js
@@ -0,0 +1,66 @@
+// just like test/gc/http-client.js,
+// but with an on('error') handler that does nothing.
+
+function serverHandler(req, res) {
+ res.writeHead(200, {'Content-Type': 'text/plain'});
+ res.end('Hello World\n');
+}
+
+var http = require('http'),
+ weak = require('weak'),
+ done = 0,
+ count = 0,
+ countGC = 0,
+ todo = 18,
+ common = require('../common.js'),
+ assert = require('assert'),
+ PORT = common.PORT;
+
+console.log('We should do '+ todo +' requests');
+
+var http = require('http');
+var server = http.createServer(serverHandler);
+server.listen(PORT, getall);
+
+function getall() {
+ for (var i = 0; i < todo; i++) {
+ (function(){
+ function cb(res) {
+ done+=1;
+ statusLater();
+ }
+ function onerror(er) {
+ throw er;
+ }
+
+ var req = http.get({
+ hostname: 'localhost',
+ pathname: '/',
+ port: PORT
+ }, cb).on('error', onerror);
+
+ count++;
+ weak(req, afterGC);
+ })()
+ }
+}
+
+function afterGC(){
+ countGC ++;
+}
+
+function statusLater() {
+ setTimeout(status, 1);
+}
+
+function status() {
+ gc();
+ console.log('Done: %d/%d', done, todo);
+ console.log('Collected: %d/%d', countGC, count);
+ if (done === todo) {
+ console.log('All should be collected now.');
+ assert(count === countGC);
+ process.exit(0);
+ }
+}
+
View
69 test/gc/test-http-client-timeout.js
@@ -0,0 +1,69 @@
+// just like test/gc/http-client.js,
+// but with a timeout set
+
+function serverHandler(req, res) {
+ setTimeout(function () {
+ res.writeHead(200)
+ res.end('hello\n');
+ }, 100);
+}
+
+var http = require('http'),
+ weak = require('weak'),
+ done = 0,
+ count = 0,
+ countGC = 0,
+ todo = 18,
+ common = require('../common.js'),
+ assert = require('assert'),
+ PORT = common.PORT;
+
+console.log('We should do '+ todo +' requests');
+
+var http = require('http');
+var server = http.createServer(serverHandler);
+server.listen(PORT, getall);
+
+function getall() {
+ for (var i = 0; i < todo; i++) {
+ (function(){
+ function cb() {
+ done+=1;
+ statusLater();
+ }
+
+ var req = http.get({
+ hostname: 'localhost',
+ pathname: '/',
+ port: PORT
+ }, cb);
+ req.on('error', cb);
+ req.setTimeout(10, function(){
+ console.log('timeout (expected)')
+ });
+
+ count++;
+ weak(req, afterGC);
+ })()
+ }
+}
+
+function afterGC(){
+ countGC ++;
+}
+
+function statusLater() {
+ setTimeout(status, 1);
+}
+
+function status() {
+ gc();
+ console.log('Done: %d/%d', done, todo);
+ console.log('Collected: %d/%d', countGC, count);
+ if (done === todo) {
+ console.log('All should be collected now.');
+ assert(count === countGC);
+ process.exit(0);
+ }
+}
+
View
63 test/gc/test-http-client.js
@@ -0,0 +1,63 @@
+// just a simple http server and client.
+
+function serverHandler(req, res) {
+ res.writeHead(200, {'Content-Type': 'text/plain'});
+ res.end('Hello World\n');
+}
+
+var http = require('http'),
+ weak = require('weak'),
+ done = 0,
+ count = 0,
+ countGC = 0,
+ todo = 5,
+ common = require('../common.js'),
+ assert = require('assert'),
+ PORT = common.PORT;
+
+console.log('We should do '+ todo +' requests');
+
+var http = require('http');
+var server = http.createServer(serverHandler);
+server.listen(PORT, getall);
+
+
+function getall() {
+ for (var i = 0; i < todo; i++) {
+ (function(){
+ function cb(res) {
+ console.error('in cb')
+ done+=1;
+ res.on('end', statusLater);
+ }
+
+ var req = http.get({
+ hostname: 'localhost',
+ pathname: '/',
+ port: PORT
+ }, cb)
+
+ count++;
+ weak(req, afterGC);
+ })()
+ }
+}
+
+function afterGC(){
+ countGC ++;
+}
+
+function statusLater() {
+ setTimeout(status, 1);
+}
+
+function status() {
+ gc();
+ console.log('Done: %d/%d', done, todo);
+ console.log('Collected: %d/%d', countGC, count);
+ if (done === todo) {
+ console.log('All should be collected now.');
+ assert(count === countGC);
+ process.exit(0);
+ }
+}
View
61 test/gc/test-net-timeout.js
@@ -0,0 +1,61 @@
+// just like test/gc/http-client-timeout.js,
+// but using a net server/client instead
+
+function serverHandler(sock) {
+ sock.setTimeout(120000);
+ setTimeout(function () {
+ sock.end('hello\n');
+ }, 100);
+}
+
+var net = require('net'),
+ weak = require('weak'),
+ done = 0,
+ count = 0,
+ countGC = 0,
+ todo = 18,
+ common = require('../common.js'),
+ assert = require('assert'),
+ PORT = common.PORT;
+
+console.log('We should do '+ todo +' requests');
+
+var server = net.createServer(serverHandler);
+server.listen(PORT, getall);
+
+function getall() {
+ for (var i = 0; i < todo; i++) {
+ (function(){
+ var req = net.connect(PORT, '127.0.0.1');
+ req.setTimeout(10, function() {
+ console.log('timeout (expected)')
+ req.destroy();
+ done++;
+ statusLater();
+ });
+
+ count++;
+ weak(req, afterGC);
+ })()
+ }
+}
+
+function afterGC(){
+ countGC ++;
+}
+
+function statusLater() {
+ setTimeout(status, 1);
+}
+
+function status() {
+ gc();
+ console.log('Done: %d/%d', done, todo);
+ console.log('Collected: %d/%d', countGC, count);
+ if (done === todo) {
+ console.log('All should be collected now.');
+ assert(count === countGC);
+ process.exit(0);
+ }
+}
+
View
133 test/gc/testcfg.py
@@ -0,0 +1,133 @@
+# Copyright 2008 the V8 project authors. All rights reserved.
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following
+# disclaimer in the documentation and/or other materials provided
+# with the distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+import test
+import os
+import shutil
+from shutil import rmtree
+from os import mkdir
+from glob import glob
+from os.path import join, dirname, exists
+import re
+
+
+FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
+FILES_PATTERN = re.compile(r"//\s+Files:(.*)")
+
+
+class GCTestCase(test.TestCase):
+
+ def __init__(self, path, file, mode, context, config):
+ super(GCTestCase, self).__init__(context, path, mode)
+ self.file = file
+ self.config = config
+ self.mode = mode
+ self.tmpdir = join(dirname(self.config.root), 'tmp')
+
+ def AfterRun(self, result):
+ # delete the whole tmp dir
+ try:
+ rmtree(self.tmpdir)
+ except:
+ pass
+ # make it again.
+ try:
+ mkdir(self.tmpdir)
+ except:
+ pass
+
+ def BeforeRun(self):
+ # delete the whole tmp dir
+ try:
+ rmtree(self.tmpdir)
+ except:
+ pass
+ # make it again.
+ # intermittently fails on win32, so keep trying
+ while not os.path.exists(self.tmpdir):
+ try:
+ mkdir(self.tmpdir)
+ except:
+ pass
+
+ def GetLabel(self):
+ return "%s %s" % (self.mode, self.GetName())
+
+ def GetName(self):
+ return self.path[-1]
+
+ def GetCommand(self):
+ result = [self.config.context.GetVm(self.mode)]
+ source = open(self.file).read()
+ flags_match = FLAGS_PATTERN.search(source)
+ if flags_match:
+ result += flags_match.group(1).strip().split()
+ files_match = FILES_PATTERN.search(source);
+ additional_files = []
+ if files_match:
+ additional_files += files_match.group(1).strip().split()
+ for a_file in additional_files:
+ result.append(join(dirname(self.config.root), '..', a_file))
+ result += ["--expose-gc"]
+ result += [self.file]
+ return result
+
+ def GetSource(self):
+ return open(self.file).read()
+
+
+class GCTestConfiguration(test.TestConfiguration):
+
+ def __init__(self, context, root):
+ super(GCTestConfiguration, self).__init__(context, root)
+
+ def Ls(self, path):
+ def SelectTest(name):
+ return name.startswith('test-') and name.endswith('.js')
+ return [f[:-3] for f in os.listdir(path) if SelectTest(f)]
+
+ def ListTests(self, current_path, path, mode):
+ all_tests = [current_path + [t] for t in self.Ls(join(self.root))]
+ result = []
+ for test in all_tests:
+ if self.Contains(path, test):
+ file_path = join(self.root, reduce(join, test[1:], "") + ".js")
+ result.append(GCTestCase(test, file_path, mode, self.context, self))
+ return result
+
+ def GetBuildRequirements(self):
+ return ['sample', 'sample=shell']
+
+ def GetTestStatus(self, sections, defs):
+ status_file = join(self.root, 'gc.status')
+ if exists(status_file):
+ test.ReadConfigurationInto(status_file, sections, defs)
+
+
+
+def GetConfiguration(context, root):
+ return GCTestConfiguration(context, root)
View
2 tools/test.py
@@ -1275,7 +1275,7 @@ def ExpandCommand(args):
return ExpandCommand
-BUILT_IN_TESTS = ['simple', 'pummel', 'message', 'internet']
+BUILT_IN_TESTS = ['simple', 'pummel', 'message', 'internet', 'gc']
def GetSuites(test_root):

0 comments on commit e63c782

Please sign in to comment.
Something went wrong with that request. Please try again.