|
|
|
#!/usr/bin/env python
|
|
|
|
|
|
|
|
# igcc - a read-eval-print loop for C/C++ programmers
|
|
|
|
#
|
|
|
|
# Copyright (C) 2009 Andy Balaam
|
|
|
|
#
|
|
|
|
# This program is free software; you can redistribute it and/or
|
|
|
|
# modify it under the terms of the GNU General Public License
|
|
|
|
# as published by the Free Software Foundation; either version 2
|
|
|
|
# of the License, or (at your option) any later version.
|
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with this program; if not, write to the Free Software
|
|
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
# MA 02110-1301, USA.
|
|
|
|
|
|
|
|
import re
|
|
|
|
|
|
|
|
import libigcc.run
|
|
|
|
from libigcc.run import UserInput
|
|
|
|
import libigcc.source_code
|
|
|
|
import libigcc.version
|
|
|
|
|
|
|
|
|
|
|
|
class FakeWriteableFile:
|
|
|
|
def __init__(self):
|
|
|
|
self.lines = []
|
|
|
|
|
|
|
|
def write(self, line):
|
|
|
|
self.lines.append(line)
|
|
|
|
|
|
|
|
|
|
|
|
class FakeReadableFile:
|
|
|
|
def __init__(self, lines):
|
|
|
|
self.lines = lines
|
|
|
|
|
|
|
|
def readline(self):
|
|
|
|
if len(self.lines) == 0:
|
|
|
|
return None
|
|
|
|
line = self.lines[0]
|
|
|
|
self.lines = self.lines[1:]
|
|
|
|
return line
|
|
|
|
|
|
|
|
|
|
|
|
def assert_strings_equal(str1, str2):
|
|
|
|
if str1 == str2:
|
|
|
|
return
|
|
|
|
|
|
|
|
raise AssertionError("\n" + str1 + "\n!=\n" + str2)
|
|
|
|
|
|
|
|
|
|
|
|
def assert_strings_match(string, re_string):
|
|
|
|
cmp_re = re.compile(re_string, re.DOTALL)
|
|
|
|
|
|
|
|
if cmp_re.match(string):
|
|
|
|
return
|
|
|
|
|
|
|
|
raise AssertionError(
|
|
|
|
"\n" + string + "\ndoes not match regular expression\n" + re_string
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def run_program(commands, expected_output, print_welcome=False, argv=None):
|
|
|
|
|
|
|
|
outputfile = FakeWriteableFile()
|
|
|
|
stdinfile = FakeReadableFile(commands)
|
|
|
|
ret = libigcc.run.run(outputfile, stdinfile, print_welcome, argv)
|
|
|
|
|
|
|
|
assert_strings_equal("".join(outputfile.lines), expected_output)
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
|
|
|
def run_program_regex_output(commands, expected_output_re):
|
|
|
|
outputfile = FakeWriteableFile()
|
|
|
|
stdinfile = FakeReadableFile(commands)
|
|
|
|
libigcc.run.run(outputfile, stdinfile, False)
|
|
|
|
|
|
|
|
assert_strings_match("".join(outputfile.lines), expected_output_re)
|
|
|
|
|
|
|
|
|
|
|
|
def test_declare_var():
|
|
|
|
commands = ["int a;"]
|
|
|
|
expected_output = "g++> int a;\ng++> \n"
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_declare_var_assign():
|
|
|
|
commands = ["int a;", "a = 10;"]
|
|
|
|
expected_output = "g++> int a;\ng++> a = 10;\ng++> \n"
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_declare_and_assign_var_then_print():
|
|
|
|
commands = ["int a = 10;", 'printf( "%d\\n", a );']
|
|
|
|
|
|
|
|
expected_output = """g++> int a = 10;
|
|
|
|
g++> printf( "%d\\n", a );
|
|
|
|
10
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_print_twice():
|
|
|
|
commands = ["int a = 10;", 'printf( "%d\\n", a );', "++a;", 'printf( "%d\\n", a );']
|
|
|
|
|
|
|
|
expected_output = """g++> int a = 10;
|
|
|
|
g++> printf( "%d\\n", a );
|
|
|
|
10
|
|
|
|
g++> ++a;
|
|
|
|
g++> printf( "%d\\n", a );
|
|
|
|
11
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_compile_error():
|
|
|
|
commands = ["int a"] # no semicolon
|
|
|
|
|
|
|
|
expected_output = """g++> int a
|
|
|
|
[Compile error - type .e to see it.]
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_compile_error_display():
|
|
|
|
commands = ["int a", ".e"] # no semicolon
|
|
|
|
|
|
|
|
# Just look for a string "xpected" in the compiler output.
|
|
|
|
expected_output_re = """g\+\+\> int a
|
|
|
|
\[Compile error - type .e to see it\.\]
|
|
|
|
g\+\+\> \.e
|
|
|
|
.*error:.*
|
|
|
|
g\+\+\>
|
|
|
|
$"""
|
|
|
|
|
|
|
|
run_program_regex_output(commands, expected_output_re)
|
|
|
|
|
|
|
|
|
|
|
|
def test_include():
|
|
|
|
commands = [
|
|
|
|
"#include <vector>",
|
|
|
|
"std::vector<int> vec;",
|
|
|
|
r'printf( "%d\n", vec.size() );',
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> #include <vector>
|
|
|
|
g++> std::vector<int> vec;
|
|
|
|
g++> printf( "%d\n", vec.size() );
|
|
|
|
0
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_multiple_repeated_includes():
|
|
|
|
commands = [
|
|
|
|
" # include <vector>",
|
|
|
|
"std::vector<int> vec;",
|
|
|
|
"#include <iostream>",
|
|
|
|
" # include <vector>",
|
|
|
|
"#include <iostream>",
|
|
|
|
"using namespace std;",
|
|
|
|
"cout << vec.size() << std::endl;",
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> # include <vector>
|
|
|
|
g++> std::vector<int> vec;
|
|
|
|
g++> #include <iostream>
|
|
|
|
g++> # include <vector>
|
|
|
|
g++> #include <iostream>
|
|
|
|
g++> using namespace std;
|
|
|
|
g++> cout << vec.size() << std::endl;
|
|
|
|
0
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_list_program():
|
|
|
|
commands = ["int a;", "a += 2;", "#include <vector>", ".l"]
|
|
|
|
|
|
|
|
expected_output = r"""g++> int a;
|
|
|
|
g++> a += 2;
|
|
|
|
g++> #include <vector>
|
|
|
|
g++> .l
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
int a;
|
|
|
|
a += 2;
|
|
|
|
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
class FakeRunner:
|
|
|
|
def __init__(self, user_commands_string, user_includes_string):
|
|
|
|
self.user_commands_string = user_commands_string
|
|
|
|
self.user_includes_string = user_includes_string
|
|
|
|
|
|
|
|
def get_user_commands_string(self):
|
|
|
|
return self.user_commands_string
|
|
|
|
|
|
|
|
def get_user_includes_string(self):
|
|
|
|
return self.user_includes_string
|
|
|
|
|
|
|
|
|
|
|
|
def test_list_full_program():
|
|
|
|
commands = ["int a;", "a += 2;", "#include <vector>", ".L"]
|
|
|
|
|
|
|
|
fakerunner = FakeRunner("int a;\na += 2;\n", "#include <vector>\n")
|
|
|
|
|
|
|
|
expected_output = """g++> int a;
|
|
|
|
g++> a += 2;
|
|
|
|
g++> #include <vector>
|
|
|
|
g++> .L
|
|
|
|
%s
|
|
|
|
g++>
|
|
|
|
""" % libigcc.source_code.get_full_source(
|
|
|
|
fakerunner
|
|
|
|
)
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_help_message():
|
|
|
|
commands = [".h"]
|
|
|
|
|
|
|
|
expected_output_re = ".*Show this help message"
|
|
|
|
|
|
|
|
run_program_regex_output(commands, expected_output_re)
|
|
|
|
|
|
|
|
|
|
|
|
def test_quit():
|
|
|
|
commands = [".q"]
|
|
|
|
|
|
|
|
expected_output = "g++> .q\n"
|
|
|
|
|
|
|
|
ret = run_program(commands, expected_output)
|
|
|
|
|
|
|
|
assert_strings_equal(ret, "quit")
|
|
|
|
|
|
|
|
|
|
|
|
def test_welcome_message():
|
|
|
|
commands = []
|
|
|
|
expected_output = (
|
|
|
|
"""igcc $version
|
|
|
|
Released under GNU GPL version 2 or later, with NO WARRANTY.
|
|
|
|
Type ".h" for help.
|
|
|
|
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
).replace("$version", libigcc.version.VERSION)
|
|
|
|
|
|
|
|
run_program(commands, expected_output, True)
|
|
|
|
|
|
|
|
|
|
|
|
def test_include_dir_on_cmd_line():
|
|
|
|
commands = ['#include "hello.h"', "hello();"]
|
|
|
|
|
|
|
|
expected_output = """g++> #include "hello.h"
|
|
|
|
g++> hello();
|
|
|
|
Hello,
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
argv = ["-I", "test/cpp"]
|
|
|
|
|
|
|
|
run_program(commands, expected_output, argv=argv)
|
|
|
|
|
|
|
|
|
|
|
|
def test_2_include_dirs_on_cmd_line():
|
|
|
|
commands = [
|
|
|
|
'#include "hello.h"',
|
|
|
|
"hello();",
|
|
|
|
'#include "world.h"',
|
|
|
|
"world();",
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = """g++> #include "hello.h"
|
|
|
|
g++> hello();
|
|
|
|
Hello,
|
|
|
|
g++> #include "world.h"
|
|
|
|
g++> world();
|
|
|
|
world!
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
argv = ["-I", "test/cpp", "-I", "test/cpp2"]
|
|
|
|
|
|
|
|
run_program(commands, expected_output, argv=argv)
|
|
|
|
|
|
|
|
|
|
|
|
def test_lib():
|
|
|
|
commands = [
|
|
|
|
'#include "math.h"',
|
|
|
|
"int a = max( 4, 6 );",
|
|
|
|
r'printf( "%d\n", a );',
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> #include "math.h"
|
|
|
|
g++> int a = max( 4, 6 );
|
|
|
|
g++> printf( "%d\n", a );
|
|
|
|
6
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
argv = ["-lm"]
|
|
|
|
|
|
|
|
run_program(commands, expected_output, argv=argv)
|
|
|
|
|
|
|
|
|
|
|
|
def test_print_license():
|
|
|
|
commands = [".c"]
|
|
|
|
|
|
|
|
expected_output_re = r"""g\+\+\> \.c
|
|
|
|
.*GNU GENERAL PUBLIC LICENSE.*
|
|
|
|
g\+\+\>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program_regex_output(commands, expected_output_re)
|
|
|
|
|
|
|
|
|
|
|
|
def test_print_warranty():
|
|
|
|
commands = [".w"]
|
|
|
|
|
|
|
|
expected_output_re = r"""g\+\+\> \.w
|
|
|
|
.*Disclaimer of Warranty.*
|
|
|
|
g\+\+\>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program_regex_output(commands, expected_output_re)
|
|
|
|
|
|
|
|
|
|
|
|
def test_runner_get_user_input():
|
|
|
|
runner = libigcc.run.Runner(None, None, None)
|
|
|
|
runner.user_input = [
|
|
|
|
UserInput("0", UserInput.COMMAND),
|
|
|
|
UserInput("1", UserInput.COMMAND),
|
|
|
|
UserInput("2", UserInput.COMMAND),
|
|
|
|
]
|
|
|
|
runner.input_num = 3
|
|
|
|
assert tuple(runner.get_user_input()) == (
|
|
|
|
UserInput("0", UserInput.COMMAND),
|
|
|
|
UserInput("1", UserInput.COMMAND),
|
|
|
|
UserInput("2", UserInput.COMMAND),
|
|
|
|
)
|
|
|
|
|
|
|
|
runner.input_num = 2
|
|
|
|
assert tuple(runner.get_user_input()) == (
|
|
|
|
UserInput("0", UserInput.COMMAND),
|
|
|
|
UserInput("1", UserInput.COMMAND),
|
|
|
|
)
|
|
|
|
|
|
|
|
runner.input_num = 1
|
|
|
|
assert tuple(runner.get_user_input()) == (UserInput("0", UserInput.COMMAND),)
|
|
|
|
|
|
|
|
|
|
|
|
def test_runner_get_user_commands():
|
|
|
|
runner = libigcc.run.Runner(None, None, None)
|
|
|
|
runner.user_input = [
|
|
|
|
UserInput("0", UserInput.COMMAND),
|
|
|
|
UserInput("1", UserInput.COMMAND),
|
|
|
|
UserInput("X", UserInput.INCLUDE),
|
|
|
|
UserInput("2", UserInput.COMMAND),
|
|
|
|
]
|
|
|
|
runner.input_num = 4
|
|
|
|
assert tuple(runner.get_user_commands()) == ("0", "1", "2")
|
|
|
|
|
|
|
|
runner.input_num = 2
|
|
|
|
assert tuple(runner.get_user_commands()) == ("0", "1")
|
|
|
|
|
|
|
|
runner.input_num = 1
|
|
|
|
assert tuple(runner.get_user_commands()) == ("0",)
|
|
|
|
|
|
|
|
|
|
|
|
def test_undo_1():
|
|
|
|
commands = [
|
|
|
|
"int a;",
|
|
|
|
"a = 5;",
|
|
|
|
"foobar",
|
|
|
|
".u",
|
|
|
|
"cout << a << endl;",
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> int a;
|
|
|
|
g++> a = 5;
|
|
|
|
g++> foobar
|
|
|
|
[Compile error - type .e to see it.]
|
|
|
|
g++> .u
|
|
|
|
[Undone 'foobar'.]
|
|
|
|
g++> cout << a << endl;
|
|
|
|
5
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_undo_2():
|
|
|
|
commands = [
|
|
|
|
"int a = 5;",
|
|
|
|
"++a;",
|
|
|
|
"++a;",
|
|
|
|
"++a;",
|
|
|
|
".u",
|
|
|
|
".u",
|
|
|
|
"cout << a << endl;",
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> int a = 5;
|
|
|
|
g++> ++a;
|
|
|
|
g++> ++a;
|
|
|
|
g++> ++a;
|
|
|
|
g++> .u
|
|
|
|
[Undone '++a;'.]
|
|
|
|
g++> .u
|
|
|
|
[Undone '++a;'.]
|
|
|
|
g++> cout << a << endl;
|
|
|
|
6
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_undo_before_beginning():
|
|
|
|
commands = [
|
|
|
|
"int a = 5;",
|
|
|
|
".u",
|
|
|
|
".u",
|
|
|
|
".u",
|
|
|
|
"cout << a << endl;",
|
|
|
|
".u",
|
|
|
|
"int b = 7;",
|
|
|
|
"cout << b << endl;",
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> int a = 5;
|
|
|
|
g++> .u
|
|
|
|
[Undone 'int a = 5;'.]
|
|
|
|
g++> .u
|
|
|
|
[Nothing to undo.]
|
|
|
|
g++> .u
|
|
|
|
[Nothing to undo.]
|
|
|
|
g++> cout << a << endl;
|
|
|
|
[Compile error - type .e to see it.]
|
|
|
|
g++> .u
|
|
|
|
[Undone 'cout << a << endl;'.]
|
|
|
|
g++> int b = 7;
|
|
|
|
g++> cout << b << endl;
|
|
|
|
7
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_undo_includes_and_commands():
|
|
|
|
commands = [
|
|
|
|
"int a = 5;",
|
|
|
|
"#include <vector>",
|
|
|
|
"++a;",
|
|
|
|
".u",
|
|
|
|
".u",
|
|
|
|
".u",
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> int a = 5;
|
|
|
|
g++> #include <vector>
|
|
|
|
g++> ++a;
|
|
|
|
g++> .u
|
|
|
|
[Undone '++a;'.]
|
|
|
|
g++> .u
|
|
|
|
[Undone '#include <vector>'.]
|
|
|
|
g++> .u
|
|
|
|
[Undone 'int a = 5;'.]
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_redo_1():
|
|
|
|
commands = [
|
|
|
|
"int a = 1;",
|
|
|
|
"++a;",
|
|
|
|
".u",
|
|
|
|
".r",
|
|
|
|
"cout << a << endl;",
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> int a = 1;
|
|
|
|
g++> ++a;
|
|
|
|
g++> .u
|
|
|
|
[Undone '++a;'.]
|
|
|
|
g++> .r
|
|
|
|
[Redone '++a;'.]
|
|
|
|
g++> cout << a << endl;
|
|
|
|
2
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_redo_2():
|
|
|
|
commands = [
|
|
|
|
"int a = 1;",
|
|
|
|
"++a;",
|
|
|
|
".u",
|
|
|
|
".u",
|
|
|
|
".r",
|
|
|
|
".r",
|
|
|
|
"cout << a << endl;",
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> int a = 1;
|
|
|
|
g++> ++a;
|
|
|
|
g++> .u
|
|
|
|
[Undone '++a;'.]
|
|
|
|
g++> .u
|
|
|
|
[Undone 'int a = 1;'.]
|
|
|
|
g++> .r
|
|
|
|
[Redone 'int a = 1;'.]
|
|
|
|
g++> .r
|
|
|
|
[Redone '++a;'.]
|
|
|
|
g++> cout << a << endl;
|
|
|
|
2
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_redo_before_beginning():
|
|
|
|
commands = [
|
|
|
|
"int a = 1;",
|
|
|
|
"++a;",
|
|
|
|
".u",
|
|
|
|
".u",
|
|
|
|
".u",
|
|
|
|
".r",
|
|
|
|
".r",
|
|
|
|
"cout << a << endl;",
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> int a = 1;
|
|
|
|
g++> ++a;
|
|
|
|
g++> .u
|
|
|
|
[Undone '++a;'.]
|
|
|
|
g++> .u
|
|
|
|
[Undone 'int a = 1;'.]
|
|
|
|
g++> .u
|
|
|
|
[Nothing to undo.]
|
|
|
|
g++> .r
|
|
|
|
[Redone 'int a = 1;'.]
|
|
|
|
g++> .r
|
|
|
|
[Redone '++a;'.]
|
|
|
|
g++> cout << a << endl;
|
|
|
|
2
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_redo_after_end():
|
|
|
|
commands = [
|
|
|
|
"int a = 1;",
|
|
|
|
"++a;",
|
|
|
|
".u",
|
|
|
|
".r",
|
|
|
|
".r",
|
|
|
|
"cout << a << endl;",
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> int a = 1;
|
|
|
|
g++> ++a;
|
|
|
|
g++> .u
|
|
|
|
[Undone '++a;'.]
|
|
|
|
g++> .r
|
|
|
|
[Redone '++a;'.]
|
|
|
|
g++> .r
|
|
|
|
[Nothing to redo.]
|
|
|
|
g++> cout << a << endl;
|
|
|
|
2
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_redo_includes_and_commands():
|
|
|
|
commands = [
|
|
|
|
"int a = 5;",
|
|
|
|
"#include <vector>",
|
|
|
|
"++a;",
|
|
|
|
".u",
|
|
|
|
".u",
|
|
|
|
".u",
|
|
|
|
".r",
|
|
|
|
".r",
|
|
|
|
".r",
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> int a = 5;
|
|
|
|
g++> #include <vector>
|
|
|
|
g++> ++a;
|
|
|
|
g++> .u
|
|
|
|
[Undone '++a;'.]
|
|
|
|
g++> .u
|
|
|
|
[Undone '#include <vector>'.]
|
|
|
|
g++> .u
|
|
|
|
[Undone 'int a = 5;'.]
|
|
|
|
g++> .r
|
|
|
|
[Redone 'int a = 5;'.]
|
|
|
|
g++> .r
|
|
|
|
[Redone '#include <vector>'.]
|
|
|
|
g++> .r
|
|
|
|
[Redone '++a;'.]
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_undo_then_new_commands():
|
|
|
|
commands = [
|
|
|
|
"int a = 5;",
|
|
|
|
"++a;",
|
|
|
|
".u",
|
|
|
|
"--a;",
|
|
|
|
"--a;",
|
|
|
|
".u",
|
|
|
|
"cout << a << endl;",
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> int a = 5;
|
|
|
|
g++> ++a;
|
|
|
|
g++> .u
|
|
|
|
[Undone '++a;'.]
|
|
|
|
g++> --a;
|
|
|
|
g++> --a;
|
|
|
|
g++> .u
|
|
|
|
[Undone '--a;'.]
|
|
|
|
g++> cout << a << endl;
|
|
|
|
4
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_undo_redo_with_output():
|
|
|
|
commands = [
|
|
|
|
"int a = 56;",
|
|
|
|
"cout << a << endl;",
|
|
|
|
".u",
|
|
|
|
".r",
|
|
|
|
".u",
|
|
|
|
"cout << 12 << endl;",
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> int a = 56;
|
|
|
|
g++> cout << a << endl;
|
|
|
|
56
|
|
|
|
g++> .u
|
|
|
|
[Undone 'cout << a << endl;'.]
|
|
|
|
g++> .r
|
|
|
|
[Redone 'cout << a << endl;'.]
|
|
|
|
56
|
|
|
|
g++> .u
|
|
|
|
[Undone 'cout << a << endl;'.]
|
|
|
|
g++> cout << 12 << endl;
|
|
|
|
12
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_print_stderr_twice():
|
|
|
|
commands = ["int a = 10;", "cerr << a << endl;", "++a;", "cerr << a << endl;"]
|
|
|
|
|
|
|
|
expected_output = """g++> int a = 10;
|
|
|
|
g++> cerr << a << endl;
|
|
|
|
10
|
|
|
|
g++> ++a;
|
|
|
|
g++> cerr << a << endl;
|
|
|
|
11
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_print_stderr_stdout():
|
|
|
|
commands = ["int a = 10;", "cerr << a << endl;", "++a;", "cout << a << endl;"]
|
|
|
|
|
|
|
|
expected_output = """g++> int a = 10;
|
|
|
|
g++> cerr << a << endl;
|
|
|
|
10
|
|
|
|
g++> ++a;
|
|
|
|
g++> cout << a << endl;
|
|
|
|
11
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def test_undo_stderr_then_new_commands():
|
|
|
|
commands = [
|
|
|
|
"int a = 5;",
|
|
|
|
"++a;",
|
|
|
|
".u",
|
|
|
|
"--a;",
|
|
|
|
"--a;",
|
|
|
|
".u",
|
|
|
|
"cerr << a << endl;",
|
|
|
|
]
|
|
|
|
|
|
|
|
expected_output = r"""g++> int a = 5;
|
|
|
|
g++> ++a;
|
|
|
|
g++> .u
|
|
|
|
[Undone '++a;'.]
|
|
|
|
g++> --a;
|
|
|
|
g++> --a;
|
|
|
|
g++> .u
|
|
|
|
[Undone '--a;'.]
|
|
|
|
g++> cerr << a << endl;
|
|
|
|
4
|
|
|
|
g++>
|
|
|
|
"""
|
|
|
|
|
|
|
|
run_program(commands, expected_output)
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
test_declare_var()
|
|
|
|
test_declare_var_assign()
|
|
|
|
test_declare_and_assign_var_then_print()
|
|
|
|
test_print_twice()
|
|
|
|
test_compile_error()
|
|
|
|
test_compile_error_display()
|
|
|
|
test_include()
|
|
|
|
test_multiple_repeated_includes()
|
|
|
|
test_list_program()
|
|
|
|
test_list_full_program()
|
|
|
|
test_help_message()
|
|
|
|
test_quit()
|
|
|
|
test_welcome_message()
|
|
|
|
test_include_dir_on_cmd_line()
|
|
|
|
test_2_include_dirs_on_cmd_line()
|
|
|
|
test_lib()
|
|
|
|
test_print_license()
|
|
|
|
test_print_warranty()
|
|
|
|
test_runner_get_user_input()
|
|
|
|
test_runner_get_user_commands()
|
|
|
|
test_undo_1()
|
|
|
|
test_undo_2()
|
|
|
|
test_undo_before_beginning()
|
|
|
|
test_undo_includes_and_commands()
|
|
|
|
test_redo_1()
|
|
|
|
test_redo_2()
|
|
|
|
test_redo_before_beginning()
|
|
|
|
test_redo_after_end()
|
|
|
|
test_redo_includes_and_commands()
|
|
|
|
test_undo_then_new_commands()
|
|
|
|
test_undo_redo_with_output()
|
|
|
|
test_print_stderr_twice()
|
|
|
|
test_print_stderr_stdout()
|
|
|
|
test_undo_stderr_then_new_commands()
|
|
|
|
|
|
|
|
# test_readline_history();
|
|
|
|
# test_print_command();
|
|
|
|
# test_edit_in_vim();
|
|
|
|
# test_compile_warning()
|
|
|
|
# test_remove_compile_error_message()
|
|
|
|
|
|
|
|
print("All tests passed.")
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|