Path: blob/main/python/python-wasm/src/test/posix/socket.test.ts
1067 views
// This breaks randomly, due to probably threading issues, since this is the error:1// "ENOENT: no such file or directory, uv_cwd"2// Hence we have to skip it for now.34import { asyncPython } from "../../node";56const CREATE_SERVER =7"import socket; s = socket.create_server(('localhost', 0)); s.listen(1)";89// See also packages/python-wasm/data/socket for some python scripts10// you can run directly.1112test.skip("create a client and a server and have them send/recv strings", async () => {13// It is really cool how easily we can do this test due to the14// architecture of python-wasm!15// We just run two completely separate copies of Python16// at the same time in memory, one as the client and one as the server. Each17// gets their own independent thread and separate WebAssembly memory, but this18// is actually all happening inside one single operating system process.19const client = await asyncPython();20const server = await asyncPython();2122// We let Python assign an available port.23await server.exec(CREATE_SERVER);24// Get the port that Python assigned:25const port = eval(await server.repr("s.getsockname()[1]"));26expect(port).toBeGreaterThan(0);27// Create a server that accepts one connection, sends "Hello",28// then receives 6 bytes and saves them. We do not await29// this call since this blocks until after server one client.30server.exec(`31conn, addr = s.accept()32conn.send(b"Hello")33received = conn.recv(6)34conn.close()35`);36// Make the client connect to the server.37await client.exec(38`import socket; conn = socket.create_connection(("localhost", ${port}))`39);40// Get Hello and confirm it worked.41expect(await client.repr("conn.recv(5)")).toBe("b'Hello'");42// Now send back "CoWasm" to the server43await client.exec("conn.send(b'CoWasm')");44// Confirm that the server received CoWasm45expect(await server.repr("received")).toBe("b'CoWasm'");4647client.kernel.terminate();48server.kernel.terminate();49});5051// socket.settimeout is very commonly used on sockets and uses fd_fdstat_set_flags in WASI52// so we better test that it doesn't crash.5354test.skip("settimeout on a socket", async () => {55const client = await asyncPython();56const server = await asyncPython();57await server.exec(CREATE_SERVER);58const port = eval(await server.repr("s.getsockname()[1]"));59expect(port).toBeGreaterThan(0);6061(async () => {62try {63// We wrap this since it is supposed to throw when we terminate the server.64await server.exec(`65conn, addr = s.accept()66import time; time.sleep(0.25)67conn.send(b"Hello")68# never close conn and never send anything.69time.sleep(1)70`);71} catch (err) {}72})();73await client.exec(74`import socket; conn = socket.create_connection(("localhost", ${port}))`75);76// Set a timeout and see that reading still happens quickly.77await client.exec("conn.settimeout(1000)");78// Get Hello and confirm it worked.79expect(await client.repr("conn.recv(5)")).toBe("b'Hello'");8081// Make timeout short:82await client.exec("conn.settimeout(0.5)");83// Try to get more and confirm it stopped trying84// quickly a bit after the timeout, showing the timeout85// actually works.86const start = new Date().valueOf();87try {88await client.repr("conn.recv(6)");89} catch (err) {}90expect(new Date().valueOf() - start).toBeLessThan(1000); // less than 1 second.91expect(new Date().valueOf() - start).toBeGreaterThan(400);9293client.kernel.terminate();94server.kernel.terminate();95});969798