diff options
author | Jeremiah Senkpiel <fishrock123@rocketmail.com> | 2016-05-20 19:05:54 -0400 |
---|---|---|
committer | Jeremiah Senkpiel <fishrock123@rocketmail.com> | 2016-06-01 18:59:01 -0400 |
commit | 88804b84ecb298d9e6525a6fbd0266ea5c357c35 (patch) | |
tree | 61b79fd57e3472b7e9c979b98690fec1e263f60a /test | |
parent | 98de4abae3e9d5d8890d0f1017aa116a4b87b7e1 (diff) | |
download | android-node-v8-88804b84ecb298d9e6525a6fbd0266ea5c357c35.tar.gz android-node-v8-88804b84ecb298d9e6525a6fbd0266ea5c357c35.tar.bz2 android-node-v8-88804b84ecb298d9e6525a6fbd0266ea5c357c35.zip |
test: test TTY problems by fakeing a TTY using openpty
Many thanks to thefourtheye and addaleax who helped make the python
bits of this possible.
See https://github.com/nodejs/node/issues/6980 for more info regarding
the related TTY issues.
Refs: https://github.com/nodejs/node/issues/6456
Refs: https://github.com/nodejs/node/pull/6773
Refs: https://github.com/nodejs/node/pull/6816
PR-URL: https://github.com/nodejs/node/pull/6895
Reviewed-By: Rod Vagg <rod@vagg.org>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Diffstat (limited to 'test')
-rw-r--r-- | test/pseudo-tty/no_dropped_stdio.js | 15 | ||||
-rw-r--r-- | test/pseudo-tty/no_dropped_stdio.out | 21 | ||||
-rw-r--r-- | test/pseudo-tty/no_interleaved_stdio.js | 17 | ||||
-rw-r--r-- | test/pseudo-tty/no_interleaved_stdio.out | 21 | ||||
-rw-r--r-- | test/pseudo-tty/testcfg.py | 161 |
5 files changed, 235 insertions, 0 deletions
diff --git a/test/pseudo-tty/no_dropped_stdio.js b/test/pseudo-tty/no_dropped_stdio.js new file mode 100644 index 0000000000..1a20889073 --- /dev/null +++ b/test/pseudo-tty/no_dropped_stdio.js @@ -0,0 +1,15 @@ +// https://github.com/nodejs/node/issues/6456#issuecomment-219320599 +// https://gist.github.com/isaacs/1495b91ec66b21d30b10572d72ad2cdd +'use strict'; +require('../common'); + +// 1000 bytes wrapped at 50 columns +// \n turns into a double-byte character +// (48 + {2}) * 20 = 1000 +var out = ('o'.repeat(48) + '\n').repeat(20); +// Add the remaining 24 bytes and terminate with an 'O'. +// This results in 1025 bytes, just enough to overflow the 1kb OS X TTY buffer. +out += 'o'.repeat(24) + 'O'; + +process.stdout.write(out); +process.exit(0); diff --git a/test/pseudo-tty/no_dropped_stdio.out b/test/pseudo-tty/no_dropped_stdio.out new file mode 100644 index 0000000000..78d2b7a365 --- /dev/null +++ b/test/pseudo-tty/no_dropped_stdio.out @@ -0,0 +1,21 @@ +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooO diff --git a/test/pseudo-tty/no_interleaved_stdio.js b/test/pseudo-tty/no_interleaved_stdio.js new file mode 100644 index 0000000000..778b2c0958 --- /dev/null +++ b/test/pseudo-tty/no_interleaved_stdio.js @@ -0,0 +1,17 @@ +// https://github.com/nodejs/node/issues/6456#issuecomment-219320599 +// https://gist.github.com/isaacs/1495b91ec66b21d30b10572d72ad2cdd +'use strict'; +require('../common'); + +// 1000 bytes wrapped at 50 columns +// \n turns into a double-byte character +// (48 + {2}) * 20 = 1000 +var out = ('o'.repeat(48) + '\n').repeat(20); +// Add the remaining 24 bytes and terminate with an 'O'. +// This results in 1025 bytes, just enough to overflow the 1kb OS X TTY buffer. +out += 'o'.repeat(24) + 'O'; + +const err = '__This is some stderr__'; + +process.stdout.write(out); +process.stderr.write(err); diff --git a/test/pseudo-tty/no_interleaved_stdio.out b/test/pseudo-tty/no_interleaved_stdio.out new file mode 100644 index 0000000000..f39b87ff46 --- /dev/null +++ b/test/pseudo-tty/no_interleaved_stdio.out @@ -0,0 +1,21 @@ +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +oooooooooooooooooooooooooooooooooooooooooooooooo +ooooooooooooooooooooooooO__This is some stderr__ diff --git a/test/pseudo-tty/testcfg.py b/test/pseudo-tty/testcfg.py new file mode 100644 index 0000000000..4699031521 --- /dev/null +++ b/test/pseudo-tty/testcfg.py @@ -0,0 +1,161 @@ +# 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 +from os.path import join, exists, basename, isdir +import re +import utils + +FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)") + +class TTYTestCase(test.TestCase): + + def __init__(self, path, file, expected, arch, mode, context, config): + super(TTYTestCase, self).__init__(context, path, arch, mode) + self.file = file + self.expected = expected + self.config = config + self.arch = arch + self.mode = mode + + def IgnoreLine(self, str): + """Ignore empty lines and valgrind output.""" + if not str.strip(): return True + else: return str.startswith('==') or str.startswith('**') + + def IsFailureOutput(self, output): + f = file(self.expected) + # Convert output lines to regexps that we can match + env = { 'basename': basename(self.file) } + patterns = [ ] + for line in f: + if not line.strip(): + continue + pattern = re.escape(line.rstrip() % env) + pattern = pattern.replace('\\*', '.*') + pattern = '^%s$' % pattern + patterns.append(pattern) + # Compare actual output with the expected + raw_lines = (output.stdout + output.stderr).split('\n') + outlines = [ s.strip() for s in raw_lines if not self.IgnoreLine(s) ] + if len(outlines) != len(patterns): + print "length differs." + print "expect=%d" % len(patterns) + print "actual=%d" % len(outlines) + print "patterns:" + for i in xrange(len(patterns)): + print "pattern = %s" % patterns[i] + print "outlines:" + for i in xrange(len(outlines)): + print "outline = %s" % outlines[i] + return True + for i in xrange(len(patterns)): + if not re.match(patterns[i], outlines[i]): + print "match failed" + print "line=%d" % i + print "expect=%s" % patterns[i] + print "actual=%s" % outlines[i] + return True + return False + + 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.arch, self.mode)] + source = open(self.file).read() + flags_match = FLAGS_PATTERN.search(source) + if flags_match: + result += flags_match.group(1).strip().split() + result.append(self.file) + return result + + def GetSource(self): + return (open(self.file).read() + + "\n--- expected output ---\n" + + open(self.expected).read()) + + def RunCommand(self, command, env): + full_command = self.context.processor(command) + output = test.Execute(full_command, + self.context, + self.context.GetTimeout(self.mode), + env, + True) + self.Cleanup() + return test.TestOutput(self, + full_command, + output, + self.context.store_unexpected_output) + + +class TTYTestConfiguration(test.TestConfiguration): + + def __init__(self, context, root): + super(TTYTestConfiguration, self).__init__(context, root) + + def Ls(self, path): + if isdir(path): + return [f[:-3] for f in os.listdir(path) if f.endswith('.js')] + else: + return [] + + def ListTests(self, current_path, path, arch, mode): + all_tests = [current_path + [t] for t in self.Ls(self.root)] + result = [] + # Skip these tests on Windows, as pseudo terminals are not available + if utils.IsWindows(): + print ("Skipping pseudo-tty tests, as pseudo terminals are not available" + " on Windows.") + return result + for test in all_tests: + if self.Contains(path, test): + file_prefix = join(self.root, reduce(join, test[1:], "")) + file_path = file_prefix + ".js" + output_path = file_prefix + ".out" + if not exists(output_path): + print "Could not find %s" % output_path + continue + result.append(TTYTestCase(test, file_path, output_path, + arch, mode, self.context, self)) + return result + + def GetBuildRequirements(self): + return ['sample', 'sample=shell'] + + def GetTestStatus(self, sections, defs): + status_file = join(self.root, 'message.status') + if exists(status_file): + test.ReadConfigurationInto(status_file, sections, defs) + + +def GetConfiguration(context, root): + return TTYTestConfiguration(context, root) |