Commits

Anonymous committed 2dd240c

Support test input in shell command implementations. Woo!

Comments (0)

Files changed (6)

src/falderal/objects.py

         >>> i.run(body='text')
         OutputOutcome('text')
 
-        >>> i = ShellImplementation('echo %(test-body-text)')
+        >>> i = ShellImplementation("echo '%(test-body-text)'")
         >>> i.run(body='text')
         OutputOutcome('text')
 
         >>> i.run(body='text')
         OutputOutcome('text')
 
+        >>> i = ShellImplementation("echo '%(test-body-text)' '%(test-input-text)'")
+        >>> i.run(body='text', input='zzrk')
+        OutputOutcome('text zzrk')
+
+        Here the body is sent to cat's stdin, but cat ignores it.
+        
+        >>> i = ShellImplementation('cat >%(output-file) <%(test-input-file)')
+        >>> i.run(body='text', input='zzrk')
+        OutputOutcome('zzrk')
+
         """
         # expand variables in the command
         test_filename = None
         output_filename = None
         command = self.command
 
+        command_contained_test_body_file = False
+        command_contained_test_body_text = False
+        command_contained_test_input_file = False
+        command_contained_test_input_text = False
+        
         # DEPRECATED
         if '%(test-file)' in self.command:
             # choose a temp file name and write the body to that file
             os.close(fd)
             # replace all occurrences in command
             command = re.sub(r'\%\(test-file\)', test_filename, command)
-            body = None
+            command_contained_test_body_file = True
         # DEPRECATED
         if '%(test-text)' in self.command:
             # escape all single quotes in body
             body = re.sub(r"'", r"\'", body)
             # replace all occurrences in command
             command = re.sub(r'\%\(test-text\)', body, command)
-            body = None
+            command_contained_test_body_text = True
 
         # Preferred over test-file
         if '%(test-body-file)' in self.command:
             os.close(fd)
             # replace all occurrences in command
             command = re.sub(r'\%\(test-body-file\)', test_filename, command)
-            body = None
+            command_contained_test_body_file = True
         # Preferred over test-text
         if '%(test-body-text)' in self.command:
             # escape all single quotes in body
             body = re.sub(r"'", r"\'", body)
             # replace all occurrences in command
             command = re.sub(r'\%\(test-body-text\)', body, command)
-            body = None
+            command_contained_test_body_text = True
+
+        if '%(test-input-file)' in self.command:
+            # choose a temp file name and write the input to that file
+            fd, test_input_filename = mkstemp(dir='.')
+            test_input_filename = basename(test_input_filename)
+            with open(test_input_filename, 'w') as file:
+                file.write(input)
+                file.close()
+            os.close(fd)
+            # replace all occurrences in command
+            command = re.sub(r'\%\(test-input-file\)', test_input_filename, command)
+            command_contained_test_input_file = True
+        if '%(test-input-text)' in self.command:
+            # escape all single quotes in input
+            body = re.sub(r"'", r"\'", body)
+            # replace all occurrences in command
+            command = re.sub(r'\%\(test-input-text\)', input, command)
+            command_contained_test_input_text = True
 
         if '%(output-file)' in self.command:
             # choose a temp file name to read output from later
         # subshell the command and return the output
         pipe = Popen(command, shell=True,
                      stdin=PIPE, stdout=PIPE, stderr=PIPE)
-        outputs = pipe.communicate(input=body)
+        # XXX How *exactly* do we decide what to send to the command's standard input?
+        # XXX Check and/or update the spec.
+        pipe_input = None
+        if not (command_contained_test_input_file or command_contained_test_input_text):
+            pipe_input = input
+        if not (command_contained_test_body_file or command_contained_test_body_text):
+            pipe_input = body
+        outputs = pipe.communicate(input=pipe_input)
         if pipe.returncode == 0:
             if output_filename is None:
                 output = self.normalize_output(outputs[0])
 bin/falderal -t || exit 1
 
 cd tests
-for TEST in test1 test2 test3 test4 test5 test9 test10 test-utf8 test-crlf; do
+for TEST in test1 test2 test3 test4 test5 test9 test10 test11 test-utf8 test-crlf; do
     echo ${TEST}...
     ../bin/falderal ${TEST}.markdown > ${TEST}.actual 2>&1
     diff -u ${TEST}.expected ${TEST}.actual || exit 1

tests/eg.silly-interpreter

+read x
+read y
+print y
+print x

tests/silly-interpreter.py

+import sys
+
+program = open(sys.argv[1]).read().split('\n')
+
+vars = {}
+for line in program:
+    if line.startswith('print '):
+        var = line[6]
+        print vars.get(var, '')
+    if line.startswith('read '):
+        var = line[5]
+        vars[var] = raw_input('')

tests/test11.expected

+--------------------------------
+Total test runs: 5, failures: 0
+--------------------------------

tests/test11.markdown

+Falderal Test 11
+----------------
+
+Test tests that have test input sections.
+
+    -> Functionality "Silly Interpreter" is implemented by
+    -> shell command "python silly-interpreter.py %(test-body-file)"
+
+    -> Tests for functionality "Silly Interpreter"
+
+    | print x
+    = 
+
+    | read x
+    | print x
+    + meow
+    = meow
+
+    | read x
+    | print x
+    + purr
+    = purr
+
+    | read x
+    | print x
+    | read y
+    | print y
+    + meow
+    + purr
+    = meow
+    = purr
+
+    | read x
+    | read y
+    | print y
+    | print x
+    + meow
+    + purr
+    = purr
+    = meow