Skip to content
This repository
Browse code

Tests for memory leaks

Conflicts:

	Makefile
  • Loading branch information...
commit e63c7821d5fc4e2f92c0606ab16b7846893ac3d1 1 parent e4dd8dc
Isaac Z. Schlueter isaacs authored
1  .gitignore
@@ -41,3 +41,4 @@ ipch/
41 41 email.md
42 42 blog.html
43 43 deps/v8-*
  44 +node_modules
18 Makefile
@@ -42,14 +42,16 @@ uninstall:
42 42 clean:
43 43 -rm -rf out/Makefile node node_g out/$(BUILDTYPE)/node blog.html email.md
44 44 -find out/ -name '*.o' -o -name '*.a' | xargs rm -rf
  45 + -rm -rf node_modules
45 46
46 47 distclean:
47 48 -rm -rf out
48 49 -rm -f config.gypi
49 50 -rm -f config.mk
50 51 -rm -rf node node_g blog.html email.md
  52 + -rm -rf node_modules
51 53
52   -test: all
  54 +test: all node_modules/weak
53 55 $(PYTHON) tools/test.py --mode=release simple message
54 56 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
55 57
@@ -59,9 +61,17 @@ test-http1: all
59 61 test-valgrind: all
60 62 $(PYTHON) tools/test.py --mode=release --valgrind simple message
61 63
62   -test-all: all
63   - python tools/test.py --mode=debug,release
64   - $(MAKE) test-npm
  64 +node_modules/weak:
  65 + @if [ ! -f node ]; then make all; fi
  66 + @if [ ! -d node_modules ]; then mkdir -p node_modules; fi
  67 + ./node deps/npm/bin/npm-cli.js install weak --prefix="$(shell pwd)"
  68 +
  69 +test-gc: all node_modules/weak
  70 + $(PYTHON) tools/test.py --mode=release gc
  71 +
  72 +test-all: all node_modules/weak
  73 + $(PYTHON) tools/test.py --mode=debug,release
  74 + make test-npm
65 75
66 76 test-all-http1: all
67 77 $(PYTHON) tools/test.py --mode=debug,release --use-http1
61 test/gc/test-http-client-connaborted.js
... ... @@ -0,0 +1,61 @@
  1 +// just like test/gc/http-client.js,
  2 +// but aborting every connection that comes in.
  3 +
  4 +function serverHandler(req, res) {
  5 + res.connection.destroy();
  6 +}
  7 +
  8 +var http = require('http'),
  9 + weak = require('weak'),
  10 + done = 0,
  11 + count = 0,
  12 + countGC = 0,
  13 + todo = 18,
  14 + common = require('../common.js'),
  15 + assert = require('assert'),
  16 + PORT = common.PORT;
  17 +
  18 +console.log('We should do '+ todo +' requests');
  19 +
  20 +var http = require('http');
  21 +var server = http.createServer(serverHandler);
  22 +server.listen(PORT, getall);
  23 +
  24 +function getall() {
  25 + for (var i = 0; i < todo; i++) {
  26 + (function(){
  27 + function cb(res) {
  28 + done+=1;
  29 + statusLater();
  30 + }
  31 +
  32 + var req = http.get({
  33 + hostname: 'localhost',
  34 + pathname: '/',
  35 + port: PORT
  36 + }, cb).on('error', cb);
  37 +
  38 + count++;
  39 + weak(req, afterGC);
  40 + })()
  41 + }
  42 +}
  43 +
  44 +function afterGC(){
  45 + countGC ++;
  46 +}
  47 +
  48 +function statusLater() {
  49 + setTimeout(status, 1);
  50 +}
  51 +
  52 +function status() {
  53 + gc();
  54 + console.log('Done: %d/%d', done, todo);
  55 + console.log('Collected: %d/%d', countGC, count);
  56 + if (done === todo) {
  57 + console.log('All should be collected now.');
  58 + assert(count === countGC);
  59 + process.exit(0);
  60 + }
  61 +}
66 test/gc/test-http-client-onerror.js
... ... @@ -0,0 +1,66 @@
  1 +// just like test/gc/http-client.js,
  2 +// but with an on('error') handler that does nothing.
  3 +
  4 +function serverHandler(req, res) {
  5 + res.writeHead(200, {'Content-Type': 'text/plain'});
  6 + res.end('Hello World\n');
  7 +}
  8 +
  9 +var http = require('http'),
  10 + weak = require('weak'),
  11 + done = 0,
  12 + count = 0,
  13 + countGC = 0,
  14 + todo = 18,
  15 + common = require('../common.js'),
  16 + assert = require('assert'),
  17 + PORT = common.PORT;
  18 +
  19 +console.log('We should do '+ todo +' requests');
  20 +
  21 +var http = require('http');
  22 +var server = http.createServer(serverHandler);
  23 +server.listen(PORT, getall);
  24 +
  25 +function getall() {
  26 + for (var i = 0; i < todo; i++) {
  27 + (function(){
  28 + function cb(res) {
  29 + done+=1;
  30 + statusLater();
  31 + }
  32 + function onerror(er) {
  33 + throw er;
  34 + }
  35 +
  36 + var req = http.get({
  37 + hostname: 'localhost',
  38 + pathname: '/',
  39 + port: PORT
  40 + }, cb).on('error', onerror);
  41 +
  42 + count++;
  43 + weak(req, afterGC);
  44 + })()
  45 + }
  46 +}
  47 +
  48 +function afterGC(){
  49 + countGC ++;
  50 +}
  51 +
  52 +function statusLater() {
  53 + setTimeout(status, 1);
  54 +}
  55 +
  56 +function status() {
  57 + gc();
  58 + console.log('Done: %d/%d', done, todo);
  59 + console.log('Collected: %d/%d', countGC, count);
  60 + if (done === todo) {
  61 + console.log('All should be collected now.');
  62 + assert(count === countGC);
  63 + process.exit(0);
  64 + }
  65 +}
  66 +
69 test/gc/test-http-client-timeout.js
... ... @@ -0,0 +1,69 @@
  1 +// just like test/gc/http-client.js,
  2 +// but with a timeout set
  3 +
  4 +function serverHandler(req, res) {
  5 + setTimeout(function () {
  6 + res.writeHead(200)
  7 + res.end('hello\n');
  8 + }, 100);
  9 +}
  10 +
  11 +var http = require('http'),
  12 + weak = require('weak'),
  13 + done = 0,
  14 + count = 0,
  15 + countGC = 0,
  16 + todo = 18,
  17 + common = require('../common.js'),
  18 + assert = require('assert'),
  19 + PORT = common.PORT;
  20 +
  21 +console.log('We should do '+ todo +' requests');
  22 +
  23 +var http = require('http');
  24 +var server = http.createServer(serverHandler);
  25 +server.listen(PORT, getall);
  26 +
  27 +function getall() {
  28 + for (var i = 0; i < todo; i++) {
  29 + (function(){
  30 + function cb() {
  31 + done+=1;
  32 + statusLater();
  33 + }
  34 +
  35 + var req = http.get({
  36 + hostname: 'localhost',
  37 + pathname: '/',
  38 + port: PORT
  39 + }, cb);
  40 + req.on('error', cb);
  41 + req.setTimeout(10, function(){
  42 + console.log('timeout (expected)')
  43 + });
  44 +
  45 + count++;
  46 + weak(req, afterGC);
  47 + })()
  48 + }
  49 +}
  50 +
  51 +function afterGC(){
  52 + countGC ++;
  53 +}
  54 +
  55 +function statusLater() {
  56 + setTimeout(status, 1);
  57 +}
  58 +
  59 +function status() {
  60 + gc();
  61 + console.log('Done: %d/%d', done, todo);
  62 + console.log('Collected: %d/%d', countGC, count);
  63 + if (done === todo) {
  64 + console.log('All should be collected now.');
  65 + assert(count === countGC);
  66 + process.exit(0);
  67 + }
  68 +}
  69 +
63 test/gc/test-http-client.js
... ... @@ -0,0 +1,63 @@
  1 +// just a simple http server and client.
  2 +
  3 +function serverHandler(req, res) {
  4 + res.writeHead(200, {'Content-Type': 'text/plain'});
  5 + res.end('Hello World\n');
  6 +}
  7 +
  8 +var http = require('http'),
  9 + weak = require('weak'),
  10 + done = 0,
  11 + count = 0,
  12 + countGC = 0,
  13 + todo = 5,
  14 + common = require('../common.js'),
  15 + assert = require('assert'),
  16 + PORT = common.PORT;
  17 +
  18 +console.log('We should do '+ todo +' requests');
  19 +
  20 +var http = require('http');
  21 +var server = http.createServer(serverHandler);
  22 +server.listen(PORT, getall);
  23 +
  24 +
  25 +function getall() {
  26 + for (var i = 0; i < todo; i++) {
  27 + (function(){
  28 + function cb(res) {
  29 + console.error('in cb')
  30 + done+=1;
  31 + res.on('end', statusLater);
  32 + }
  33 +
  34 + var req = http.get({
  35 + hostname: 'localhost',
  36 + pathname: '/',
  37 + port: PORT
  38 + }, cb)
  39 +
  40 + count++;
  41 + weak(req, afterGC);
  42 + })()
  43 + }
  44 +}
  45 +
  46 +function afterGC(){
  47 + countGC ++;
  48 +}
  49 +
  50 +function statusLater() {
  51 + setTimeout(status, 1);
  52 +}
  53 +
  54 +function status() {
  55 + gc();
  56 + console.log('Done: %d/%d', done, todo);
  57 + console.log('Collected: %d/%d', countGC, count);
  58 + if (done === todo) {
  59 + console.log('All should be collected now.');
  60 + assert(count === countGC);
  61 + process.exit(0);
  62 + }
  63 +}
61 test/gc/test-net-timeout.js
... ... @@ -0,0 +1,61 @@
  1 +// just like test/gc/http-client-timeout.js,
  2 +// but using a net server/client instead
  3 +
  4 +function serverHandler(sock) {
  5 + sock.setTimeout(120000);
  6 + setTimeout(function () {
  7 + sock.end('hello\n');
  8 + }, 100);
  9 +}
  10 +
  11 +var net = require('net'),
  12 + weak = require('weak'),
  13 + done = 0,
  14 + count = 0,
  15 + countGC = 0,
  16 + todo = 18,
  17 + common = require('../common.js'),
  18 + assert = require('assert'),
  19 + PORT = common.PORT;
  20 +
  21 +console.log('We should do '+ todo +' requests');
  22 +
  23 +var server = net.createServer(serverHandler);
  24 +server.listen(PORT, getall);
  25 +
  26 +function getall() {
  27 + for (var i = 0; i < todo; i++) {
  28 + (function(){
  29 + var req = net.connect(PORT, '127.0.0.1');
  30 + req.setTimeout(10, function() {
  31 + console.log('timeout (expected)')
  32 + req.destroy();
  33 + done++;
  34 + statusLater();
  35 + });
  36 +
  37 + count++;
  38 + weak(req, afterGC);
  39 + })()
  40 + }
  41 +}
  42 +
  43 +function afterGC(){
  44 + countGC ++;
  45 +}
  46 +
  47 +function statusLater() {
  48 + setTimeout(status, 1);
  49 +}
  50 +
  51 +function status() {
  52 + gc();
  53 + console.log('Done: %d/%d', done, todo);
  54 + console.log('Collected: %d/%d', countGC, count);
  55 + if (done === todo) {
  56 + console.log('All should be collected now.');
  57 + assert(count === countGC);
  58 + process.exit(0);
  59 + }
  60 +}
  61 +
133 test/gc/testcfg.py
... ... @@ -0,0 +1,133 @@
  1 +# Copyright 2008 the V8 project authors. All rights reserved.
  2 +# Redistribution and use in source and binary forms, with or without
  3 +# modification, are permitted provided that the following conditions are
  4 +# met:
  5 +#
  6 +# * Redistributions of source code must retain the above copyright
  7 +# notice, this list of conditions and the following disclaimer.
  8 +# * Redistributions in binary form must reproduce the above
  9 +# copyright notice, this list of conditions and the following
  10 +# disclaimer in the documentation and/or other materials provided
  11 +# with the distribution.
  12 +# * Neither the name of Google Inc. nor the names of its
  13 +# contributors may be used to endorse or promote products derived
  14 +# from this software without specific prior written permission.
  15 +#
  16 +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17 +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18 +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  19 +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  20 +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  21 +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  22 +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23 +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24 +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25 +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  26 +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27 +
  28 +import test
  29 +import os
  30 +import shutil
  31 +from shutil import rmtree
  32 +from os import mkdir
  33 +from glob import glob
  34 +from os.path import join, dirname, exists
  35 +import re
  36 +
  37 +
  38 +FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
  39 +FILES_PATTERN = re.compile(r"//\s+Files:(.*)")
  40 +
  41 +
  42 +class GCTestCase(test.TestCase):
  43 +
  44 + def __init__(self, path, file, mode, context, config):
  45 + super(GCTestCase, self).__init__(context, path, mode)
  46 + self.file = file
  47 + self.config = config
  48 + self.mode = mode
  49 + self.tmpdir = join(dirname(self.config.root), 'tmp')
  50 +
  51 + def AfterRun(self, result):
  52 + # delete the whole tmp dir
  53 + try:
  54 + rmtree(self.tmpdir)
  55 + except:
  56 + pass
  57 + # make it again.
  58 + try:
  59 + mkdir(self.tmpdir)
  60 + except:
  61 + pass
  62 +
  63 + def BeforeRun(self):
  64 + # delete the whole tmp dir
  65 + try:
  66 + rmtree(self.tmpdir)
  67 + except:
  68 + pass
  69 + # make it again.
  70 + # intermittently fails on win32, so keep trying
  71 + while not os.path.exists(self.tmpdir):
  72 + try:
  73 + mkdir(self.tmpdir)
  74 + except:
  75 + pass
  76 +
  77 + def GetLabel(self):
  78 + return "%s %s" % (self.mode, self.GetName())
  79 +
  80 + def GetName(self):
  81 + return self.path[-1]
  82 +
  83 + def GetCommand(self):
  84 + result = [self.config.context.GetVm(self.mode)]
  85 + source = open(self.file).read()
  86 + flags_match = FLAGS_PATTERN.search(source)
  87 + if flags_match:
  88 + result += flags_match.group(1).strip().split()
  89 + files_match = FILES_PATTERN.search(source);
  90 + additional_files = []
  91 + if files_match:
  92 + additional_files += files_match.group(1).strip().split()
  93 + for a_file in additional_files:
  94 + result.append(join(dirname(self.config.root), '..', a_file))
  95 + result += ["--expose-gc"]
  96 + result += [self.file]
  97 + return result
  98 +
  99 + def GetSource(self):
  100 + return open(self.file).read()
  101 +
  102 +
  103 +class GCTestConfiguration(test.TestConfiguration):
  104 +
  105 + def __init__(self, context, root):
  106 + super(GCTestConfiguration, self).__init__(context, root)
  107 +
  108 + def Ls(self, path):
  109 + def SelectTest(name):
  110 + return name.startswith('test-') and name.endswith('.js')
  111 + return [f[:-3] for f in os.listdir(path) if SelectTest(f)]
  112 +
  113 + def ListTests(self, current_path, path, mode):
  114 + all_tests = [current_path + [t] for t in self.Ls(join(self.root))]
  115 + result = []
  116 + for test in all_tests:
  117 + if self.Contains(path, test):
  118 + file_path = join(self.root, reduce(join, test[1:], "") + ".js")
  119 + result.append(GCTestCase(test, file_path, mode, self.context, self))
  120 + return result
  121 +
  122 + def GetBuildRequirements(self):
  123 + return ['sample', 'sample=shell']
  124 +
  125 + def GetTestStatus(self, sections, defs):
  126 + status_file = join(self.root, 'gc.status')
  127 + if exists(status_file):
  128 + test.ReadConfigurationInto(status_file, sections, defs)
  129 +
  130 +
  131 +
  132 +def GetConfiguration(context, root):
  133 + return GCTestConfiguration(context, root)
2  tools/test.py
@@ -1275,7 +1275,7 @@ def ExpandCommand(args):
1275 1275 return ExpandCommand
1276 1276
1277 1277
1278   -BUILT_IN_TESTS = ['simple', 'pummel', 'message', 'internet']
  1278 +BUILT_IN_TESTS = ['simple', 'pummel', 'message', 'internet', 'gc']
1279 1279
1280 1280
1281 1281 def GetSuites(test_root):

0 comments on commit e63c782

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