From 54f4a18dbc5188f4c6ffc1706543b1b6884fb66b Mon Sep 17 00:00:00 2001
From: Frank Sauerburger <frank@sauerburger.com>
Date: Thu, 3 Aug 2017 22:05:37 +0200
Subject: [PATCH] Implement OpConsoleOutput

Implement the operation console_output, which runs the listed commands and check
that the output matches.
---
 .gitlab-ci.yml           |  2 +-
 doxec/__init__.py        | 26 +++++++++++++++++++++++++-
 doxec/tests/operation.py | 27 ++++++++++++++++++++++++++-
 3 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index ea2c233..09f4f73 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -6,7 +6,7 @@ stages:
 doxec_unittest:
   stage: test
   script:
-    - python3 -m unittest doxec.tests
+    - python3 -m unittest -v doxec.tests
 
      
 doxec_doctest:
diff --git a/doxec/__init__.py b/doxec/__init__.py
index 301bb25..7ef09e5 100644
--- a/doxec/__init__.py
+++ b/doxec/__init__.py
@@ -94,6 +94,7 @@ class OpConsole(Operation):
         if job.returncode != 0:
             raise TestException("Script failed with %d:" % job.returncode,
                 stdoutdata.decode('utf8'), stderrdata.decode('utf8'))
+        return stdoutdata
                 
 
 
@@ -105,7 +106,30 @@ class OpConsoleOutput(Operation):
     command = "console_output"
 
     def execute(self):
-        pass
+        commands = []  # items are (command, [output lines])
+        for line in self.content:
+            if line.startswith("$"):
+                commands.append((line[1:], []))
+            elif len(commands) == 0:
+                # no command yet
+                continue
+            else:
+                commands[-1][1].append(line)
+
+        for command, lines in commands:
+            job = subprocess.Popen("/bin/bash", stdin=subprocess.PIPE,
+                stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+            (stdoutdata, stderrdata) = job.communicate(command.encode('utf8'))
+            if job.returncode != 0:
+                raise TestException("Script failed with %d:" % job.returncode,
+                    stdoutdata.decode('utf8'), stderrdata.decode('utf8'))
+            output = stdoutdata.decode('utf8')
+            output = re.split(r'\r?\n', output)
+            if len(output) > 0 and output[-1] == '':
+                del output[-1] 
+            if lines != output:
+                raise TestException("Output differs", lines, output)
+       
 
 # add operations to op_store
 Operation.op_store.append(OpConsole)
diff --git a/doxec/tests/operation.py b/doxec/tests/operation.py
index 3f31c18..c1fa108 100644
--- a/doxec/tests/operation.py
+++ b/doxec/tests/operation.py
@@ -169,4 +169,29 @@ class OpConsoleOutputTestCase(unittest.TestCase):
     Test the functionality of the console-output-operation. This test case focuses on
     the execute method.
     """
-    pass
+    
+    def test_execute_pass(self):
+        """
+        Creates an OpConsoleOutput operation and checks that no exception is raised,
+        when the expected output matches the actual output.
+        """
+        console = OpConsoleOutput(None,
+            ["$ echo 'Hi'", "Hi", "$ echo 'Hello\n  World'", "Hello", "  World"])
+        console.execute()
+
+    def test_execute_fail(self):
+        """
+        Creates an OpConsoleOutput operation and checks that an exception is raised,
+        when the expected output does not match the actual output.
+        """
+        console = OpConsoleOutput(None,
+            ["$ echo 'Hi'", "Hi", "$ echo 'Hello\n  World'", "Hello", "Moon"])
+        self.assertRaises(TestException, console.execute)
+
+    def test_execute_leading_comments(self):
+        """
+        Creates an OpConsoleOutput operation and checks whether leading
+        non-code lines are ignored.
+        """
+        console = OpConsoleOutput(None, ["heyho", "$ echo 'Hi'", "Hi"])
+        console.execute()
-- 
GitLab