1

I'm making a simple quiz app that asks a user to write a source code. For example, a user is asked to "Given n values, add them and print it". Input is

N
a[0], a[1], ..., a[N-1]

and output is

s

For example, an input is

3
1 3 5

and an output is

9

A user should write

N = int(input())
print(sum(([int(input()) for i input().split()))

The source code should be in string because a user answers in HTML input and submits it to a server.

Given the above context, how would you test source code in string which contains input and print?

My work-in-progress code is

# source should be assigned with the payload of from HTTP POST request
source = `print([int(input()) for i in range(N))`
# How to feed an input and validate an output?
assertEqual(correct_answer, exec(source))

I was thinking to use exec, but not sure how I can feed input for input() programatically.

At least, you can redirect stdout for print.

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Watanabe.N
  • 1,549
  • 1
  • 14
  • 37
  • Okay, so why don't you use `exec` to execute the code, and compare the output with the expected result? – mkrieger1 May 06 '23 at 09:03
  • @mkrieger1: Because they don't know how to feed the input in: "I was thinking to use exec, but not sure how I can feed input programatically." – user2357112 May 06 '23 at 09:04
  • 1
    (As an aside, there are serious security problems with doing this, and someone who doesn't know how to redirect stdin probably does not have the kind of expertise needed to safely sandbox untrusted code.) – user2357112 May 06 '23 at 09:05
  • yeah, that's another problem I'll search next. – Watanabe.N May 06 '23 at 09:09
  • @mkrieger1: No, it's not about getting the source code. It's about passing input *to* that source code. See that `input()` call in `source`? They don't know how to feed input to *that*. – user2357112 May 06 '23 at 09:11
  • 1
    If you want to test at function with `input` here is a way to give it with code: https://stackoverflow.com/questions/35851323/how-to-test-a-function-with-input-call – Tzane May 06 '23 at 09:49

1 Answers1

0

The code below works as expected on Python 3.9. It monkey patches sys.stdin and sys.stdout, though an environment should be sandboxed.

import sys
from io import StringIO
saved_stdin = sys.stdin
saved_stdout = sys.stdout

y = 9
class PatchInput():
    def __init__(self):
        self.x = iter(['3', '1 3 5'])

    def readline(self):
        return next(self.x)

strIO = StringIO()
sys.stdin = PatchInput()
sys.stdout = strIO

source = 'input()\nprint(sum([int(i) for i in input().split()]))'
exec(source)
p = int(strIO.getvalue())

strIO.close()
sys.stdout = saved_stdout

assert p == y
Watanabe.N
  • 1,549
  • 1
  • 14
  • 37