-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathtest_single_shell_interactive.py
More file actions
129 lines (117 loc) · 4.13 KB
/
Copy pathtest_single_shell_interactive.py
File metadata and controls
129 lines (117 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
from concurrent.futures import Future
import os
import subprocess
import queue
import unittest
from executorlib import SingleNodeExecutor
from executorlib.standalone.serialize import cloudpickle_register
from executorlib.task_scheduler.interactive.blockallocation import _execute_multiple_tasks
from executorlib.standalone.interactive.spawner import MpiExecSpawner
executable_path = os.path.join(os.path.dirname(__file__), "..", "executables", "count.py")
def init_process():
return {
"process": subprocess.Popen(
["python", executable_path],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
universal_newlines=True,
shell=False,
)
}
def interact(shell_input, process, lines_to_read=None, stop_read_pattern=None):
process.stdin.write(shell_input)
process.stdin.flush()
lines_count = 0
output = ""
while True:
output_current = process.stdout.readline()
output += output_current
lines_count += 1
if stop_read_pattern is not None and stop_read_pattern in output_current:
break
elif lines_to_read is not None and lines_to_read == lines_count:
break
return output
def shutdown(process):
process.stdin.write("shutdown\n")
process.stdin.flush()
class ShellInteractiveExecutorTest(unittest.TestCase):
def test_execute_single_task(self):
test_queue = queue.Queue()
future_lines = Future()
future_pattern = Future()
future_shutdown = Future()
test_queue.put(
{
"fn": interact,
"future": future_lines,
"args": (),
"kwargs": {
"shell_input": "4\n",
"lines_to_read": 5,
"stop_read_pattern": None,
},
}
)
test_queue.put(
{
"fn": interact,
"future": future_pattern,
"args": (),
"kwargs": {
"shell_input": "4\n",
"lines_to_read": None,
"stop_read_pattern": "done",
},
}
)
test_queue.put(
{
"fn": shutdown,
"future": future_shutdown,
"args": (),
"kwargs": {},
}
)
test_queue.put({"shutdown": True, "wait": True})
cloudpickle_register(ind=1)
self.assertFalse(future_lines.done())
self.assertFalse(future_pattern.done())
_execute_multiple_tasks(
future_queue=test_queue,
cores=1,
openmpi_oversubscribe=False,
spawner=MpiExecSpawner,
init_function=init_process,
)
self.assertTrue(future_lines.done())
self.assertTrue(future_pattern.done())
self.assertTrue(future_shutdown.done())
self.assertEqual("0\n1\n2\n3\ndone\n", future_lines.result())
self.assertEqual("0\n1\n2\n3\ndone\n", future_pattern.result())
test_queue.join()
def test_shell_interactive_executor(self):
cloudpickle_register(ind=1)
with SingleNodeExecutor(
max_workers=1,
init_function=init_process,
block_allocation=True,
) as exe:
future_lines = exe.submit(
interact, shell_input="4\n", lines_to_read=5, stop_read_pattern=None
)
future_pattern = exe.submit(
interact,
shell_input="4\n",
lines_to_read=None,
stop_read_pattern="done",
)
self.assertFalse(future_lines.done())
self.assertFalse(future_pattern.done())
self.assertEqual("0\n1\n2\n3\ndone\n", future_lines.result())
self.assertEqual("0\n1\n2\n3\ndone\n", future_pattern.result())
self.assertTrue(future_lines.done())
self.assertTrue(future_pattern.done())
future_shutdown = exe.submit(shutdown)
self.assertIsNone(future_shutdown.result())
self.assertTrue(future_shutdown.done())