diff --git a/llvm/utils/lit/lit/TestRunner.py b/llvm/utils/lit/lit/TestRunner.py --- a/llvm/utils/lit/lit/TestRunner.py +++ b/llvm/utils/lit/lit/TestRunner.py @@ -57,12 +57,20 @@ """Mutable shell environment containing things like CWD and env vars. - Environment variables are not implemented, but cwd tracking is. + Environment variables are not implemented, but cwd tracking is. In addition, + we maintain a dir stack for pushd/popd. """ def __init__(self, cwd, env): self.cwd = cwd self.env = dict(env) + self.dirStack = [] + + def change_dir(self, newdir): + if os.path.isabs(newdir): + self.cwd = newdir + else: + self.cwd = os.path.realpath(os.path.join(self.cwd, newdir)) class TimeoutHelper(object): """ @@ -275,17 +283,30 @@ def executeBuiltinCd(cmd, shenv): """executeBuiltinCd - Change the current directory.""" if len(cmd.args) != 2: - raise InternalShellError("'cd' supports only one argument") - newdir = cmd.args[1] + raise InternalShellError(cmd, "'cd' supports only one argument") # Update the cwd in the parent environment. - if os.path.isabs(newdir): - shenv.cwd = newdir - else: - shenv.cwd = os.path.realpath(os.path.join(shenv.cwd, newdir)) + shenv.change_dir(cmd.args[1]) # The cd builtin always succeeds. If the directory does not exist, the # following Popen calls will fail instead. return ShellCommandResult(cmd, "", "", 0, False) +def executeBuiltinPushd(cmd, shenv): + """executeBuiltinPushd - Change the current dir and save the old.""" + if len(cmd.args) != 2: + raise InternalShellError(cmd, "'pushd' supports only one argument") + shenv.dirStack.append(shenv.cwd) + shenv.change_dir(cmd.args[1]) + return ShellCommandResult(cmd, "", "", 0, False) + +def executeBuiltinPopd(cmd, shenv): + """executeBuiltinPopd - Restore a previously saved working directory.""" + if len(cmd.args) != 1: + raise InternalShellError(cmd, "'popd' does not support arguments") + if not shenv.dirStack: + raise InternalShellError(cmd, "popd: directory stack empty") + shenv.cwd = shenv.dirStack.pop() + return ShellCommandResult(cmd, "", "", 0, False) + def executeBuiltinExport(cmd, shenv): """executeBuiltinExport - Set an environment variable.""" if len(cmd.args) != 2: @@ -629,6 +650,8 @@ 'export': executeBuiltinExport, 'echo': executeBuiltinEcho, 'mkdir': executeBuiltinMkdir, + 'popd': executeBuiltinPopd, + 'pushd': executeBuiltinPushd, 'rm': executeBuiltinRm, ':': executeBuiltinColon} # To avoid deadlock, we use a single stderr stream for piped diff --git a/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/lit.cfg b/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/lit.cfg new file mode 100644 --- /dev/null +++ b/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/lit.cfg @@ -0,0 +1,4 @@ +import lit.formats +config.name = 'shtest-pushd-popd' +config.suffixes = ['.txt'] +config.test_format = lit.formats.ShTest(execute_external=False) diff --git a/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/popd-args.txt b/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/popd-args.txt new file mode 100644 --- /dev/null +++ b/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/popd-args.txt @@ -0,0 +1 @@ +# RUN: popd invalid \ No newline at end of file diff --git a/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/popd-no-stack.txt b/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/popd-no-stack.txt new file mode 100644 --- /dev/null +++ b/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/popd-no-stack.txt @@ -0,0 +1 @@ +# RUN: popd \ No newline at end of file diff --git a/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/pushd-popd-ok.txt b/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/pushd-popd-ok.txt new file mode 100644 --- /dev/null +++ b/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/pushd-popd-ok.txt @@ -0,0 +1,8 @@ +# RUN: rm -rf %t/UserFoo && mkdir -p %t/UserFoo/FooDocs +# RUN: touch %t/UserFoo/user.txt %t/UserFoo/FooDocs/doc.txt +# RUN: pushd %t/UserFoo +# RUN: pushd FooDocs +# RUN: cat doc.txt +# RUN: popd +# RUN: cat user.txt +# RUN: popd \ No newline at end of file diff --git a/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/pushd-too-many-args.txt b/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/pushd-too-many-args.txt new file mode 100644 --- /dev/null +++ b/llvm/utils/lit/tests/Inputs/shtest-pushd-popd/pushd-too-many-args.txt @@ -0,0 +1 @@ +# RUN: pushd a b \ No newline at end of file diff --git a/llvm/utils/lit/tests/shtest-pushd-popd.py b/llvm/utils/lit/tests/shtest-pushd-popd.py new file mode 100644 --- /dev/null +++ b/llvm/utils/lit/tests/shtest-pushd-popd.py @@ -0,0 +1,24 @@ +# Check the pushd and popd commands + +# RUN: not %{lit} -a -v %{inputs}/shtest-pushd-popd \ +# RUN: | FileCheck -match-full-lines %s +# +# END. + +# CHECK: -- Testing: 4 tests{{.*}} + +# CHECK: FAIL: shtest-pushd-popd :: popd-args.txt ({{[^)]*}}) +# CHECK: $ "popd" "invalid" +# CHECK: 'popd' does not support arguments + +# CHECK: FAIL: shtest-pushd-popd :: popd-no-stack.txt ({{[^)]*}}) +# CHECK: $ "popd" +# CHECK: popd: directory stack empty + +# CHECK: FAIL: shtest-pushd-popd :: pushd-too-many-args.txt ({{[^)]*}}) +# CHECK: $ "pushd" "a" "b" +# CHECK: 'pushd' supports only one argument + +# CHECK: Passed: 1 +# CHECK: Failed: 3 +# CHECK-NOT: {{.}}