def test_s3270_sscp_lu(self): # Start 'playback' to read s3270's output. pport, socket = cti.unused_port() with playback.playback(self, 's3270/Test/sscp-lu.trc', port=pport) as p: socket.close() # Start s3270. hport, socket = cti.unused_port() s3270 = Popen(cti.vgwrap(['s3270', '-httpd', str(hport), f"127.0.0.1:{pport}"]), stdin=DEVNULL, stdout=DEVNULL) self.children.append(s3270) socket.close() # Send initial negotiations and the first SSCP-LU message. p.send_records(21) # Make sure the emulator has switched to SSCP-LU mode. r = requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/PrintText(string,oia)') self.assertTrue(r.ok, 'Expected PrintText()) to succeed') self.assertEqual('4BS', r.json()['result'][-1][0:3], 'Expected SSCP-LU mode') # Send another SSCP-LU and then a regular 3270 record. p.send_records(2) # Make sure the emulator is back to 3270 mode. r = requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/PrintText(string,oia)') self.assertTrue(r.ok, 'Expected PrintText()) to succeed') self.assertEqual('4B ', r.json()['result'][-1][0:3], 'Expected 3270 mode') # Wait for the processes to exit. r = requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/Quit()') self.vgwait(s3270)
def b3270_multi_address(self, ipv4=True, ipv6=True): # Start b3270. args46 = [] if not ipv4: args46 += ['-6'] if not ipv6: args46 += ['-4'] hport, ts = cti.unused_port() b3270 = Popen(cti.vgwrap(['b3270', '-json', '-httpd', str(hport)] + args46), stdin=PIPE, stdout=PIPE) self.children.append(b3270) ts.close() self.check_listen(hport) # Drain the first line of output. On Windows, unless this is done, b3270 # will block on the pipe. b3270.stdout.readline() # Feed b3270 some actions. uport, ts = cti.unused_port() ts.close() requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/Open({setupHosts.test_hostname}:{uport})') requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/Quit()') self.check_result(b3270, ipv4, ipv6) # Wait for the process to exit. self.vgwait(b3270)
def b3270_ma_switch_test(self, ipv4=True, ipv6=True): hport, ts = cti.unused_port() b3270 = Popen(cti.vgwrap(['b3270', '-json', '-httpd', str(hport)]), stdin=PIPE, stdout=PIPE) self.children.append(b3270) ts.close() self.check_listen(hport) # Drain the first line of output. On Windows, unless this is done, b3270 # will block on the pipe. b3270.stdout.readline() # Feed b3270 some actions. uport, ts = cti.unused_port() ts.close() if ipv4: requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/Set(preferIpv4,true)') if ipv6: requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/Set(preferIpv6,true)') requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/Open({setupHosts.test_hostname}:{uport})') requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/Quit()') self.check_result(b3270, ipv4, ipv6) # Wait for the process to exit. self.vgwait(b3270)
def test_x3270_retry_cancel(self): # Find an unused port, but do not listen on it yet. playback_port, pts = cti.unused_port() # Start x3270. hport, hts = cti.unused_port() hts.close() x3270 = Popen( cti.vgwrap([ 'x3270', '-set', 'retry', '-httpd', str(hport), '127.0.0.1:{playback_port}' ])) self.children.append(x3270) # Wait for the Connection Error pop-up to appear. self.try_until(self.find_popup, 4, 'Connect error pop-up did not appear') # Make it stop. os.system( "xdotool search --onlyvisible --name 'x3270 Error' windowfocus mousemove --window %1 42 63 click 1" ) # Verify that x3270 is no longer reconnecting. r = requests.get( f'http://127.0.0.1:{hport}/3270/rest/json/printtext string oia' ).json()['result'] self.assertEqual('X Not Connected', r[-1][7:22]) requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/quit') self.vgwait(x3270) pts.close()
def test_s3270_cp937(self): expect_chinese = [ ' 辦理中止委託轉帳代繳,須提供原代繳帳號,申辦資料如有疑義或不明,經本公司聯繫補', '正資料,請配合提供補正;不願提供者不予受理。 ' ] # Start playback. pport, ts = cti.unused_port() with playback.playback(self, 's3270/Test/937.trc', port=pport) as p: ts.close() # Start s3270. sport, ts = cti.unused_port() s3270 = Popen( cti.vgwrap([ 's3270', '-httpd', str(sport), '-utf8', '-codepage', 'cp937', f'127.0.0.1:{pport}' ])) self.children.append(s3270) self.check_listen(sport) ts.close() # Fill up the screen. p.send_records(1) # Check the DBCS output. r = requests.get( f'http://127.0.0.1:{sport}/3270/rest/json/Ascii1(2,1,2,80)') self.assertEqual(expect_chinese, r.json()['result']) # Wait for the process to exit successfully. requests.get(f'http://127.0.0.1:{sport}/3270/rest/json/Quit()') self.vgwait(s3270)
def test_nops(self): # Start 'playback' to drive s3270. pport, pts = cti.unused_port() with playback.playback(self, 's3270/Test/ibmlink.trc', port=pport) as p: pts.close() # Start s3270 with a webserver. sport, sts = cti.unused_port() s3270 = Popen( cti.vgwrap([ "s3270", "-httpd", f"127.0.0.1:{sport}", f"127.0.0.1:{pport}" ])) self.children.append(s3270) self.check_listen(sport) sts.close() # Get to the login screen. p.send_records(4) self.nop(sport, 'Wait(CursorAt,21,13)') self.nop(sport, 'Wait(InputFieldAt,21,13)') self.nop(sport, 'Wait(StringAt,21,13,"___")') requests.get(f'http://127.0.0.1:{sport}/3270/rest/json/Quit()') self.vgwait(s3270)
def test_s3270_sscp_lu(self): # Start 'playback' to emulate the host. pport, socket = cti.unused_port() with playback.playback(self, 's3270/Test/wont-tn3270e.trc', port=pport) as p: socket.close() # Start s3270. hport, socket = cti.unused_port() s3270 = Popen(cti.vgwrap( ['s3270', '-httpd', str(hport), f"127.0.0.1:{pport}"]), stdin=DEVNULL, stdout=DEVNULL) self.children.append(s3270) socket.close() self.check_listen(hport) # Send negotiations and make sure the responses match, but don't disconnect. p.match(disconnect=False) # Make sure the emulator is in 3270 mode now. r = requests.get( f'http://127.0.0.1:{hport}/3270/rest/json/PrintText(string,oia)' ) self.assertTrue(r.ok, 'Expected PrintText()) to succeed') self.assertEqual('4A ', r.json()['result'][-1][0:3], 'Expected TN3270 mode') # Wait for s3270 to exit. r = requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/Quit()') self.vgwait(s3270)
def test_s3270_cr(self): # Start 'playback' to read s3270's output. pport, socket = cti.unused_port() with playback.playback(self, 's3270/Test/contention-resolution.trc', port=pport) as p: socket.close() # Start s3270. hport, socket = cti.unused_port() s3270 = Popen(cti.vgwrap(['s3270', '-httpd', str(hport), f"127.0.0.1:{pport}"]), stdin=DEVNULL, stdout=DEVNULL) self.children.append(s3270) socket.close() # Send initial negotiations and half a screen. p.send_records(6) # Make sure the keyboard remains locked. r = requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/PrintText(string,oia)') self.assertTrue(r.ok, 'Expected PrintText()) to succeed') self.assertIn('X Wait', r.json()['result'][-1], 'Expected Wait') # Send 3270 data with SEND-DATA. p.send_records(1) # Make sure the keyboard is unlocked now. r = requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/PrintText(string,oia)') self.assertTrue(r.ok, 'Expected PrintText()) to succeed') self.assertEqual(' ', r.json()['result'][-1][11:16], 'Expected no lock') # Wait for the processes to exit. r = requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/Quit()') self.vgwait(s3270)
def c3270_multi_host(self, ipv4=True, ipv6=True): # Start c3270. handle, tracefile = tempfile.mkstemp() os.close(handle) args46 = [] if not ipv4: args46 += ['-6'] if not ipv6: args46 += ['-4'] hport, ts = cti.unused_port() (pid, fd) = pty.fork() if pid == 0: # Child process ts.close() os.environ['TERM'] = 'xterm-256color' os.execvp( cti.vgwrap_ecmd('c3270'), cti.vgwrap_eargs([ 'c3270', '-model', '2', '-httpd', str(hport), '-trace', '-tracefile', tracefile, '-secure' ] + args46)) self.assertTrue(False, 'c3270 did not start') # Parent. self.check_listen(hport) ts.close() # Feed c3270 some actions. uport, ts = cti.unused_port() ts.close() requests.get( f'http://127.0.0.1:{hport}/3270/rest/json/Open({setupHosts.test_hostname}:{uport})' ) self.assertTrue( requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/Quit()').ok, 'Quit failed') # Wait for the process to exit. self.vgwait_pid(pid) # Make sure both are processed. with open(tracefile, 'r') as file: output = file.readlines() tried = [] for line in output: m = re.search(r'Trying (.*), port', line) if m != None: tried += [m.group(1)] os.unlink(tracefile) if ipv4: self.assertIn('127.0.0.1', tried, 'Did not try IPv4') else: self.assertNotIn('127.0.0.1', tried, 'Should not try IPv4') if ipv6: self.assertIn('::1', tried, 'Did not try IPv6') else: self.assertNotIn('::1', tried, 'Should not try IPv6')
def x3270_multi_host(self, ipv4=True, ipv6=True): # Start x3270. handle, tracefile = tempfile.mkstemp() os.close(handle) args46 = [] if not ipv4: args46 += ['-6'] if not ipv6: args46 += ['-4'] hport, ts = cti.unused_port() x3270 = Popen( cti.vgwrap([ 'x3270', '-httpd', str(hport), '-trace', '-tracefile', tracefile, '-xrm', 'x3270.traceMonitor: false' ] + args46)) self.children.append(x3270) self.check_listen(hport) ts.close() # Feed x3270 some actions. uport, ts = cti.unused_port() ts.close() requests.get( f'http://127.0.0.1:{hport}/3270/rest/json/Open({setupHosts.test_hostname}:{uport})' ) self.assertTrue( requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/Quit()').ok, 'Quit failed') # Wait for the process to exit. self.vgwait(x3270) # Make sure both are processed. with open(tracefile, 'r') as file: output = file.readlines() tried = [] for line in output: m = re.search(r'Trying (.*), port', line) if m != None: tried += [m.group(1)] os.unlink(tracefile) if ipv4: self.assertIn('127.0.0.1', tried, 'Did not try IPv4') else: self.assertNotIn('127.0.0.1', tried, 'Should not try IPv4') if ipv6: self.assertIn('::1', tried, 'Did not try IPv6') else: self.assertNotIn('::1', tried, 'Should not try IPv6')
def test_b3270_reconnect_interference(self): # Start 'playback' to talk to b3270. playback_port, ts = cti.unused_port() with playback.playback(self, 'c3270/Test/ibmlink2.trc', port=playback_port) as p: ts.close() # Start b3270. hport, ts = cti.unused_port() b3270 = Popen(cti.vgwrap(['b3270', '-set', 'reconnect', '-json', '-httpd', str(hport)]), stdin=PIPE, stdout=PIPE) ts.close() self.children.append(b3270) # Throw away b3270's initialization output. pq = pipeq.pipeq(self, b3270.stdout) pq.get(2, 'b3270 did not start') # Tell b3270 to connect. b3270.stdin.write(f'"open 127.0.0.1:{playback_port}"\n'.encode('utf8')) b3270.stdin.flush() # Wait for b3270 to connect. p.wait_accept() # Asynchronously block for an input field. wait_thread = threading.Thread(target=self.wif, args = [hport]) wait_thread.start() # Wait for the Wait() to block. def wait_block(): r = ''.join(requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/Query(Tasks)').json()['result']) return 'Wait("InputField")' in r self.try_until(wait_block, 2, 'Wait() did not block') # Close the connection. p.close() # Wait for the input field thread to complete. wait_thread.join(timeout=2) self.assertFalse(wait_thread.is_alive(), 'Wait thread did not terminate') # Check. self.assertIn('Host disconnected', ''.join(self.wait_result['result'])) # Clean up. b3270.stdin.write(b'"quit"\n') b3270.stdin.flush() b3270.stdin.close() self.vgwait(b3270) pq.close() b3270.stdout.close()
def test_numeric_pr3287_session(self): # Start playback to talk to s3270. pport, ts = cti.unused_port(ipv6=True) with playback.playback(self, 's3270/Test/ibmlink.trc', port=pport, ipv6=True) as p: ts.close() # Create an s3270 session file that starts a fake printer session. handle, sname = tempfile.mkstemp(suffix='.s3270') os.close(handle) handle, tname = tempfile.mkstemp() os.close(handle) with open(sname, 'w') as file: file.write( f's3270.hostname: {setupHosts.test_hostname}:{pport}\n') file.write('s3270.printerLu: .\n') file.write( f's3270.printer.assocCommandLine: echo "%H%" >{tname} && sleep 5\n' ) # Start s3270 with that profile. os.environ['PRINTER_DELAY_MS'] = '1' hport, ts = cti.unused_port() s3270 = Popen( cti.vgwrap(['s3270', '-httpd', str(hport), '-6', sname])) self.children.append(s3270) self.check_listen(hport) ts.close() # Accept the connection and fill the screen. # This will cause s3270 to start up the printer session. p.send_records(4) # Make sure the printer session got started. self.try_until(lambda: os.path.getsize(tname) > 0, 4, 'Printer session not started') with open(tname, 'r') as file: contents = file.readlines() self.assertIn('[::1]', contents[0], 'Expected numeric host') # Wait for the process to exit. requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/Quit())') self.vgwait(s3270) os.unlink(sname) os.unlink(tname)
def test_simple_negatives(self): # Start s3270. port, ts = cti.unused_port() s3270 = Popen(cti.vgwrap(["s3270", "-httpd", f"127.0.0.1:{port}"])) self.children.append(s3270) self.check_listen(port) ts.close() # Syntax tests. self.simple_negative_test(port, 'Wait(CursorAt)', 'requires') self.simple_negative_test(port, 'Wait(CursorAt,1,2,3)', 'requires') self.simple_negative_test(port, 'Wait(CursorAt,fred,joe)', 'Invalid') self.simple_negative_test(port, 'Wait(CursorAt,9999999)', 'Invalid') self.simple_negative_test(port, 'Wait(CursorAt,300,300)', 'Invalid') self.simple_negative_test(port, 'Wait(StringAt)', 'requires') self.simple_negative_test(port, 'Wait(StringAt,1,2,3,4)', 'requires') self.simple_negative_test(port, 'Wait(InputFieldAt)', 'requires') self.simple_negative_test(port, 'Wait(InputFieldAt,1,2,3)', 'requires') # Not-connected tests. self.simple_negative_test(port, 'Wait(CursorAt,0,0)', 'connected') self.simple_negative_test(port, 'Wait(StringAt,0,0,"Hello")', 'connected') self.simple_negative_test(port, 'Wait(InputFieldAt,0,0)', 'connected') # Clean up. requests.get(f'http://127.0.0.1:{port}/3270/rest/json/Quit()') self.vgwait(s3270)
def test_c3270_interactive_script_wrong(self): # Fork c3270 with a PTY between this process and it. c3270_port, ts = cti.unused_port() os.environ['TERM'] = 'xterm-256color' (pid, fd) = pty.fork() if pid == 0: # Child process ts.close() os.execvp(cti.vgwrap_ecmd('c3270'), cti.vgwrap_eargs(['c3270', '-model', '2', '-utf8', '-secure', '-httpd', f'127.0.0.1:{c3270_port}'])) self.assertTrue(False, 'c3270 did not start') # Parent process. # Make sure c3270 started. self.check_listen(c3270_port) ts.close() # Tell c3270 to run an interactive script with invalid arguments. r = requests.get(f'http://127.0.0.1:{c3270_port}/3270/rest/json/Script(-interactive,-async,"Foo,bar"))') self.assertFalse(r.ok, 'Expected a syntax error') # Tell c3270 to exit. requests.get(f'http://127.0.0.1:{c3270_port}/3270/rest/json/Quit())') self.vgwait_pid(pid) os.close(fd)
def suffix_test(ti, program, suffix, children): # Create a session file. (handle, file) = tempfile.mkstemp(suffix=suffix) bprogram = program.encode('utf8') os.write(handle, bprogram + b'.termName: foo\n') pfx2 = b'w' + bprogram if sys.platform.startswith('win') else bprogram os.write(handle, pfx2 + b'.model: 3279-3-E\n') os.close(handle) # Start the emulator. port, ts = cti.unused_port() emu = Popen(cti.vgwrap([program, '-httpd', str(port), file]), stdout=DEVNULL) children.append(emu) cti.cti.check_listen(ti, port) ts.close() # Check the output. r = requests.get( f'http://127.0.0.1:{port}/3270/rest/json/Query(TerminalName)') j = r.json() ti.assertEqual('foo', j['result'][0], 'Expecting "foo" as the terminal name') r = requests.get(f'http://127.0.0.1:{port}/3270/rest/json/Set(model)') j = r.json() ti.assertEqual('3279-3-E', j['result'][0], 'Expecting 3279-3-E as the model') # Wait for the process to exit. requests.get(f'http://127.0.0.1:{port}/3270/rest/json/Quit()') cti.cti.vgwait(ti, emu) os.unlink(file)
def test_tcl3270_linger2(self): # Start tcl3270. port, ts = cti.unused_port() tcl3270 = Popen(cti.vgwrap([ "tcl3270", "tcl3270/Test/linger2.tcl", "--", "-httpd", f"127.0.0.1:{port}" ]), stdin=DEVNULL, stdout=DEVNULL) self.children.append(tcl3270) self.check_listen(port) ts.close() # Find the copy of s3270 it is running. tchildren = psutil.Process(tcl3270.pid).children() self.assertEqual(1, len(tchildren)) s3270 = tchildren[0] self.assertEqual('s3270', s3270.name()) # Kill s3270. os.kill(s3270.pid, signal.SIGTERM) # Make sure tcl3270 is gone, too. self.vgwait(tcl3270, assertOnFailure=False) exit_code = tcl3270.wait() self.assertEqual(98, exit_code)
def test_s3270_socket_json_semantic_error(self): # Start s3270. port, ts = cti.unused_port() s3270 = Popen( cti.vgwrap(['s3270', '-scriptport', str(port), '-scriptportonce'])) self.children.append(s3270) self.check_listen(port) ts.close() # Push a JSON-formatted command at it. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('127.0.0.1', port)) command = json.dumps({'foo': 'bar'}).encode('utf8') + b'\n' s.sendall(command) # Decode the result. result = self.recv_to_eof(s, 2) s.close() # Wait for the process to exit successfully. self.vgwait(s3270) # Test the output. j = json.loads(result) self.assertEqual("Missing object member 'action'", j['result'][0]) self.assertFalse(j['success']) self.assertTrue(j['status'].startswith('L U U N N 4 24 80 0 0 0x0 '))
def s3270_httpd_smoke(self, ipv6=False): # Start s3270. port, ts = cti.unused_port(ipv6=ipv6) loopback = '[::1]' if ipv6 else '127.0.0.1' s3270 = Popen(cti.vgwrap(["s3270", "-httpd", f'{loopback}:{port}'])) self.children.append(s3270) self.check_listen(port, ipv6=ipv6) ts.close() # Send it a JSON GET. r = requests.get( f'http://{loopback}:{port}/3270/rest/json/Set(monoCase)') s = r.json() self.assertEqual(s['result'], ['false']) self.assertTrue(s['status'].startswith('L U U N N 4 24 80 0 0 0x0 ')) # Send it a JSON POST. r = requests.post(f'http://{loopback}:{port}/3270/rest/post', json={ 'action': 'set', 'args': ['monoCase'] }) s = r.json() self.assertEqual(s['result'], ['false']) self.assertTrue(s['status'].startswith('L U U N N 4 24 80 0 0 0x0 ')) # Wait for the process to exit. requests.get(f'http://{loopback}:{port}/3270/rest/json/Quit()') self.vgwait(s3270)
def test_x3270if_smoke(self): # Start a copy of s3270 to talk to. port, ts = cti.unused_port() s3270 = Popen(["s3270", "-scriptport", f"127.0.0.1:{port}"], stdin=DEVNULL, stdout=DEVNULL) self.children.append(s3270) self.check_listen(port) ts.close() # Run x3270if with a trivial query. x3270if = Popen(cti.vgwrap( ["x3270if", "-t", str(port), "Set(startTls)"]), stdout=PIPE) self.children.append(x3270if) # Decode the result. stdout = x3270if.communicate()[0].decode('utf8') # Wait for the processes to exit. s3270.kill() self.children.remove(s3270) s3270.wait() self.vgwait(x3270if) # Test the output. self.assertEqual('true\n', stdout)
def test_s3270_httpd_persist(self): # Start s3270. port, ts = cti.unused_port() s3270 = Popen(cti.vgwrap(['s3270', '-httpd', str(port)])) self.children.append(s3270) self.check_listen(port) ts.close() # Start a requests session and do a get. # Doing the get within a session keeps the connection alive. s = requests.Session() r = s.get(f'http://127.0.0.1:{port}/3270/rest/json/Set(monoCase)') self.assertEqual(requests.codes.ok, r.status_code) self.assertEqual('false', r.json()['result'][0]) # Do it again. r = s.get(f'http://127.0.0.1:{port}/3270/rest/json/Set(monoCase)') self.assertEqual(requests.codes.ok, r.status_code) self.assertEqual('false', r.json()['result'][0]) # Make sure the connection pool is non-empty. self.assertNotEqual(0, len(r.connection.poolmanager.pools.keys())) # Wait for the process to exit successfully. s.get(f'http://127.0.0.1:{port}/3270/rest/json/Quit()') s.close() self.vgwait(s3270)
def test_s3270_tls_smoke(self): # Start a server to read s3270's output. port, ts = cti.unused_port() with tls_server.tls_server('Common/Test/tls/TEST.crt', 'Common/Test/tls/TEST.key', self, None, port) as server: ts.close() # Start s3270. args = ['s3270'] if sys.platform != 'darwin' and not sys.platform.startswith('win'): args += ['-cafile', 'Common/Test/tls/myCA.pem'] args.append(f'l:a:c:t:127.0.0.1:{port}=TEST') s3270 = Popen(cti.vgwrap(args), stdin=PIPE, stdout=DEVNULL) self.children.append(s3270) # Do the TLS thing. server.wrap() # Feed s3270 some actions. s3270.stdin.write(b"String(abc)\n") s3270.stdin.write(b"Enter()\n") s3270.stdin.write(b"Disconnect()\n") s3270.stdin.write(b"Quit()\n") s3270.stdin.flush() # Make sure they are passed through. out = server.recv_to_end() self.assertEqual(b"abc\r\n", out) # Wait for the process to exit. s3270.stdin.close() self.vgwait(s3270)
def test_s3270_socket_json(self): # Start s3270. port, ts = cti.unused_port() s3270 = Popen( cti.vgwrap(['s3270', '-scriptport', str(port), '-scriptportonce'])) self.children.append(s3270) self.check_listen(port) ts.close() # Push a JSON-formatted command at it. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('127.0.0.1', port)) command = json.dumps({ 'action': 'Set', 'args': ['startTls'] }).encode('utf8') + b'\n' s.sendall(command) # Decode the result. result = self.recv_to_eof(s, 2) s.close() # Wait for the process to exit successfully. self.vgwait(s3270) # Test the output. self.check_result_json(result)
def test_s3270_socket_json_syntax_error(self): # Start s3270. port, ts = cti.unused_port() s3270 = Popen( cti.vgwrap(['s3270', '-scriptport', str(port), '-scriptportonce'])) self.children.append(s3270) self.check_listen(port) ts.close() # Push a JSON-formatted command at it. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('127.0.0.1', port)) s.sendall(b'{"foo"}\n') # Decode the result. result = self.recv_to_eof(s, 2).split('\n') s.close() # Wait for the process to exit successfully. self.vgwait(s3270) # Test the output, which is in s3270 format. # This is because JSON parsing is inferred from the first # non-whitespace character on the line, and that guess might be wrong. self.assertEqual(4, len(result)) self.assertTrue(result[0].startswith('data: JSON parse error')) self.assertTrue(result[1].startswith('L U U N N 4 24 80 0 0 0x0 ')) self.assertEqual('error', result[2]) self.assertEqual('', result[3])
def s3270_3270_smoke(self, ipv6=False): # Start 'playback' to read s3270's output. port, ts = cti.unused_port(ipv6=ipv6) with playback.playback(self, 's3270/Test/ibmlink.trc', port=port, ipv6=ipv6) as p: ts.close() # Start s3270. loopback = '[::1]' if ipv6 else '127.0.0.1' s3270 = Popen(cti.vgwrap([ "s3270", "-xrm", "s3270.contentionResolution: false", f'{loopback}:{port}' ]), stdin=PIPE, stdout=DEVNULL) self.children.append(s3270) # Feed s3270 some actions. s3270.stdin.write(b"PF(3)\n") s3270.stdin.write(b"Quit()\n") s3270.stdin.flush() # Make sure the emulator does what we expect. p.match() # Wait for the processes to exit. s3270.stdin.close() self.vgwait(s3270)
def test_s3270_starttls(self): # Start a server to read s3270's output. port, ts = cti.unused_port() with tls_server.tls_server('Common/Test/tls/TEST.crt', 'Common/Test/tls/TEST.key', self, 's3270/Test/ibmlink.trc', port) as server: ts.close() # Start s3270. args = ['s3270', '-xrm', 's3270.contentionResolution: false'] if sys.platform != 'darwin' and not sys.platform.startswith('win'): args += ['-cafile', 'Common/Test/tls/myCA.pem'] args.append(f'127.0.0.1:{port}=TEST') s3270 = Popen(cti.vgwrap(args), stdin=PIPE, stdout=DEVNULL) self.children.append(s3270) # Make sure it all works. server.starttls() s3270.stdin.write(b"PF(3)\n") s3270.stdin.write(b"Quit()\n") s3270.stdin.flush() server.match() # Wait for the process to exit. s3270.stdin.close() self.vgwait(s3270)
def s3270_lp_term(self, model, term, override=None): # Start s3270. port, ts = cti.unused_port() args = ['s3270', '-model', model, '-httpd', str(port)] if override != None: args += ['-tn', override] args += ['-e', '/bin/bash', '-c', 's3270/Test/echo_term.bash'] s3270 = Popen(cti.vgwrap(args), stdin=DEVNULL, stdout=DEVNULL) self.check_listen(port) self.children.append(s3270) ts.close() # Wait for the script to exit and get the result. r = requests.get( f'http://127.0.0.1:{port}/3270/rest/json/Wait(Disconnect)', timeout=2) self.assertEqual(requests.codes.ok, r.status_code) r = requests.get( f'http://127.0.0.1:{port}/3270/rest/json/Ascii1(1,1,1,80)') self.assertEqual(requests.codes.ok, r.status_code) j = r.json() self.assertEqual(term, j['result'][0].strip()) requests.get(f'http://127.0.0.1:{port}/3270/rest/json/Quit()') self.vgwait(s3270)
def test_s3270_ft_cut(self): # Start 'playback' to read s3270's output. port, socket = cti.unused_port() with playback.playback(self, 's3270/Test/ft_cut.trc', port=port) as p: socket.close() # Start s3270. s3270 = Popen(cti.vgwrap( ["s3270", "-model", "2", f"127.0.0.1:{port}"]), stdin=PIPE, stdout=DEVNULL) self.children.append(s3270) # Feed s3270 some actions. s3270.stdin.write( b'transfer direction=send host=vm "localfile=s3270/Test/fttext" "hostfile=ft text a"\n' ) s3270.stdin.write(b"String(logoff)\n") s3270.stdin.write(b"Enter()\n") s3270.stdin.flush() # Verify what s3270 does. p.match() # Wait for the process to exit. s3270.stdin.close() self.vgwait(s3270)
def nvt_1049(self, mode_alt, mode_normal): # Start a server to throw NVT escape sequences at s3270. s = cti.sendserver(self) # Start s3270. hport, ts = cti.unused_port() s3270 = Popen( cti.vgwrap( ['s3270', '-httpd', str(hport), f'a:c:t:127.0.0.1:{s.port}'])) self.children.append(s3270) self.check_listen(hport) ts.close() # Send some text and read it back. s.send(b'hello') r = requests.get( f'http://127.0.0.1:{hport}/3270/rest/json/Expect(hello,1)') self.assertEqual(requests.codes.ok, r.status_code) r = requests.get( f'http://127.0.0.1:{hport}/3270/rest/json/Ascii1(1,1,1,80)') self.assertEqual(requests.codes.ok, r.status_code) self.assertEqual('hello', r.json()['result'][0].strip()) # Switch to the alternate display. s.send(b'\x1b[?1049' + mode_alt + b'there') r = requests.get( f'http://127.0.0.1:{hport}/3270/rest/json/Expect(there,1)') self.assertEqual(requests.codes.ok, r.status_code) r = requests.get( f'http://127.0.0.1:{hport}/3270/rest/json/Ascii1(1,1,1,10)') self.assertEqual(requests.codes.ok, r.status_code) self.assertEqual(' there', r.json()['result'][0]) # Switch back to the main display. Make sure it picks back up exactly as it was. s.send(b'\x1b[?1049' + mode_normal + b'fella') r = requests.get( f'http://127.0.0.1:{hport}/3270/rest/json/Expect(fella,1)') self.assertEqual(requests.codes.ok, r.status_code) r = requests.get( f'http://127.0.0.1:{hport}/3270/rest/json/Ascii1(1,1,1,10)') self.assertEqual(requests.codes.ok, r.status_code) self.assertEqual('hellofella', r.json()['result'][0]) # Alternate again. Make sure it's blank. s.send(b'\x1b[?1049' + mode_alt + b'hubba') r = requests.get( f'http://127.0.0.1:{hport}/3270/rest/json/Expect(hubba,1)') self.assertEqual(requests.codes.ok, r.status_code) r = requests.get( f'http://127.0.0.1:{hport}/3270/rest/json/Ascii1(1,1,1,15)') self.assertEqual(requests.codes.ok, r.status_code) self.assertEqual(' hubba', r.json()['result'][0]) # Clean up. s.close() requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/Quit()') self.vgwait(s3270)
def test_x3270_retry_succeed_5s(self): # Find an unused port, but do not listen on it yet. playback_port, pts = cti.unused_port() # Start x3270. hport, hts = cti.unused_port() hts.close() x3270 = Popen( cti.vgwrap([ 'x3270', '-set', 'retry', '-httpd', str(hport), f'127.0.0.1:{playback_port}' ])) self.children.append(x3270) # Wait for the Connection Error pop-up to appear. self.try_until(self.find_popup, 4, 'Connect error pop-up did not appear') # Start playback to accept the connection. with playback.playback(self, 'c3270/Test/ibmlink2.trc', port=playback_port) as p: pts.close() # Wait for x3270 to connect. p.wait_accept(timeout=6) # Wait for the status to update. def connected(): r = requests.get( f'http://127.0.0.1:{hport}/3270/rest/json/query host' ).json()['result'][0] return r == f'host 127.0.0.1 {playback_port}' self.try_until(connected, 2, 'x3270 did not connect') # Make sure the pop-up has popped itself down. self.assertFalse(self.find_popup()) requests.get(f'http://127.0.0.1:{hport}/3270/rest/json/quit') self.vgwait(x3270) pts.close()
def new_wait(self, initial_eors, second_actions, wait_params, p: playback.playback = None, n: int = 0): # Start 'playback' to drive s3270. playback_port, ts = cti.unused_port() with playback.playback(self, 's3270/Test/ibmlink.trc', port=playback_port) as p: ts.close() # Start s3270 with a webserver. s3270_port, ts = cti.unused_port() s3270 = Popen( cti.vgwrap([ "s3270", "-httpd", f"127.0.0.1:{s3270_port}", f"127.0.0.1:{playback_port}" ])) self.children.append(s3270) self.check_listen(s3270_port) ts.close() # Step until the login screen is visible. p.send_records(initial_eors) # In the background, wait for the Wait() action to block, then perform the additional actions. x = threading.Thread(target=self.to_playback, args=(s3270_port, second_actions, p, n)) x.start() # Wait for the change. r = requests.get( f'http://127.0.0.1:{s3270_port}/3270/rest/json/Wait({wait_params})', timeout=2) self.assertEqual(r.status_code, requests.codes.ok) # Wait for the processes to exit. x.join(timeout=2) requests.get(f'http://127.0.0.1:{s3270_port}/3270/rest/json/Quit()') self.vgwait(s3270)