mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 10:58:56 +00:00
* added net.Server * fix fmt * fix cast and move test * fix node-net.tests.ts but breaks server data receive * fix end and close only emitting when data or pipe was added * fix socket starting paused * add echo test * fix fmt * fix fmt * on close if the socket is paused, keep paused until the user resumes it to match node behavior * resume on connect * fix getConnections, error on close, make _Handler private and create symbols for SocketServerHandlers * add path support (IPC) * fix unix domains support, add connect unix tests * fix unix socket tests * emit listening and listening error on next tick * fix connection flask test * try fix connect error on macos test * merge connection and drop tests * added exclusive option * fix socket.zig fmt * fix validation for options and add test for it * pass prettier fmt
346 lines
9.1 KiB
TypeScript
346 lines
9.1 KiB
TypeScript
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "bun:test";
|
|
import { connect, isIP, isIPv4, isIPv6, Socket } from "net";
|
|
import { realpathSync, mkdtempSync } from "fs";
|
|
import { tmpdir } from "os";
|
|
import { join } from "path";
|
|
|
|
const socket_domain = mkdtempSync(join(realpathSync(tmpdir()), "node-net"));
|
|
|
|
it("should support net.isIP()", () => {
|
|
expect(isIP("::1")).toBe(6);
|
|
expect(isIP("foobar")).toBe(0);
|
|
expect(isIP("127.0.0.1")).toBe(4);
|
|
expect(isIP("127.0.0.1/24")).toBe(0);
|
|
expect(isIP("127.000.000.001")).toBe(0);
|
|
});
|
|
|
|
it("should support net.isIPv4()", () => {
|
|
expect(isIPv4("::1")).toBe(false);
|
|
expect(isIPv4("foobar")).toBe(false);
|
|
expect(isIPv4("127.0.0.1")).toBe(true);
|
|
expect(isIPv4("127.0.0.1/24")).toBe(false);
|
|
expect(isIPv4("127.000.000.001")).toBe(false);
|
|
});
|
|
|
|
it("should support net.isIPv6()", () => {
|
|
expect(isIPv6("::1")).toBe(true);
|
|
expect(isIPv6("foobar")).toBe(false);
|
|
expect(isIPv6("127.0.0.1")).toBe(false);
|
|
expect(isIPv6("127.0.0.1/24")).toBe(false);
|
|
expect(isIPv6("127.000.000.001")).toBe(false);
|
|
});
|
|
|
|
describe("net.Socket read", () => {
|
|
var port = 12345;
|
|
var unix_servers = 0;
|
|
for (let [message, label] of [
|
|
// ["Hello World!".repeat(1024), "long message"],
|
|
["Hello!", "short message"],
|
|
]) {
|
|
describe(label, () => {
|
|
function runWithServer(cb, unix_domain_path) {
|
|
return done => {
|
|
function drain(socket) {
|
|
const message = socket.data.message;
|
|
const written = socket.write(message);
|
|
if (written < message.length) {
|
|
socket.data.message = message.slice(written);
|
|
} else {
|
|
socket.end();
|
|
}
|
|
}
|
|
|
|
var server = Bun.listen(
|
|
unix_domain_path
|
|
? {
|
|
unix: join(unix_domain_path, `${unix_servers++}.sock`),
|
|
socket: {
|
|
open(socket) {
|
|
socket.data.message = message;
|
|
drain(socket);
|
|
},
|
|
drain,
|
|
error(socket, err) {
|
|
done(err);
|
|
},
|
|
},
|
|
data: {
|
|
message: "",
|
|
},
|
|
}
|
|
: {
|
|
hostname: "localhost",
|
|
port: port++,
|
|
socket: {
|
|
open(socket) {
|
|
socket.data.message = message;
|
|
drain(socket);
|
|
},
|
|
drain,
|
|
error(socket, err) {
|
|
done(err);
|
|
},
|
|
},
|
|
data: {
|
|
message: "",
|
|
},
|
|
},
|
|
);
|
|
|
|
function onDone(err) {
|
|
server.stop();
|
|
done(err);
|
|
}
|
|
|
|
try {
|
|
cb(server, drain, onDone);
|
|
} catch (e) {
|
|
onDone(e);
|
|
}
|
|
};
|
|
}
|
|
|
|
it(
|
|
"should work with .connect(port)",
|
|
runWithServer((server, drain, done) => {
|
|
var data = "";
|
|
const socket = new Socket()
|
|
.connect(server.port)
|
|
.on("connect", () => {
|
|
expect(socket).toBeDefined();
|
|
expect(socket.connecting).toBe(false);
|
|
})
|
|
.setEncoding("utf8")
|
|
.on("data", chunk => {
|
|
data += chunk;
|
|
})
|
|
.on("end", () => {
|
|
try {
|
|
expect(data).toBe(message);
|
|
done();
|
|
} catch (e) {
|
|
server.stop();
|
|
done(e);
|
|
}
|
|
})
|
|
.on("error", done);
|
|
}),
|
|
);
|
|
|
|
it(
|
|
"should work with .connect(port, listener)",
|
|
runWithServer((server, drain, done) => {
|
|
var data = "";
|
|
const socket = new Socket()
|
|
.connect(server.port, () => {
|
|
expect(socket).toBeDefined();
|
|
expect(socket.connecting).toBe(false);
|
|
})
|
|
.setEncoding("utf8")
|
|
.on("data", chunk => {
|
|
data += chunk;
|
|
})
|
|
.on("end", () => {
|
|
try {
|
|
expect(data).toBe(message);
|
|
done();
|
|
} catch (e) {
|
|
server.stop();
|
|
done(e);
|
|
}
|
|
})
|
|
.on("error", done);
|
|
}),
|
|
);
|
|
|
|
it(
|
|
"should work with .connect(port, host, listener)",
|
|
runWithServer((server, drain, done) => {
|
|
var data = "";
|
|
const socket = new Socket()
|
|
.connect(server.port, "localhost", () => {
|
|
expect(socket).toBeDefined();
|
|
expect(socket.connecting).toBe(false);
|
|
})
|
|
.setEncoding("utf8")
|
|
.on("data", chunk => {
|
|
data += chunk;
|
|
})
|
|
.on("end", () => {
|
|
try {
|
|
expect(data).toBe(message);
|
|
done();
|
|
} catch (e) {
|
|
done(e);
|
|
}
|
|
})
|
|
.on("error", done);
|
|
}),
|
|
);
|
|
|
|
it(
|
|
"should work with .connect(path)",
|
|
runWithServer((server, drain, done) => {
|
|
var data = "";
|
|
const socket = new Socket()
|
|
.connect(server.unix)
|
|
.on("connect", () => {
|
|
expect(socket).toBeDefined();
|
|
expect(socket.connecting).toBe(false);
|
|
})
|
|
.setEncoding("utf8")
|
|
.on("data", chunk => {
|
|
data += chunk;
|
|
})
|
|
.on("end", () => {
|
|
try {
|
|
expect(data).toBe(message);
|
|
done();
|
|
} catch (e) {
|
|
server.stop();
|
|
done(e);
|
|
}
|
|
})
|
|
.on("error", done);
|
|
}, socket_domain),
|
|
);
|
|
|
|
it(
|
|
"should work with .connect(path, listener)",
|
|
runWithServer((server, drain, done) => {
|
|
var data = "";
|
|
const socket = new Socket()
|
|
.connect(server.unix, () => {
|
|
expect(socket).toBeDefined();
|
|
expect(socket.connecting).toBe(false);
|
|
})
|
|
.setEncoding("utf8")
|
|
.on("data", chunk => {
|
|
data += chunk;
|
|
})
|
|
.on("end", () => {
|
|
try {
|
|
expect(data).toBe(message);
|
|
done();
|
|
} catch (e) {
|
|
done(e);
|
|
}
|
|
})
|
|
.on("error", done);
|
|
}, socket_domain),
|
|
);
|
|
});
|
|
}
|
|
});
|
|
|
|
describe("net.Socket write", () => {
|
|
const message = "Hello World!".repeat(1024);
|
|
let port = 53213;
|
|
|
|
function runWithServer(cb) {
|
|
return done => {
|
|
let server;
|
|
|
|
function close(socket) {
|
|
expect(Buffer.concat(socket.data).toString("utf8")).toBe(message);
|
|
done();
|
|
}
|
|
|
|
var leaky;
|
|
server = Bun.listen({
|
|
hostname: "0.0.0.0",
|
|
port: port++,
|
|
socket: {
|
|
close,
|
|
data(socket, buffer) {
|
|
leaky = socket;
|
|
if (!Buffer.isBuffer(buffer)) {
|
|
done(new Error("buffer is not a Buffer"));
|
|
}
|
|
|
|
socket.data.push(buffer);
|
|
},
|
|
end: close,
|
|
error(socket, err) {
|
|
leaky = socket;
|
|
done(err);
|
|
},
|
|
open(socket) {
|
|
leaky = socket;
|
|
socket.data = [];
|
|
},
|
|
},
|
|
data: [] as Buffer[],
|
|
});
|
|
|
|
function onDone(err) {
|
|
server.stop();
|
|
done(err);
|
|
}
|
|
|
|
try {
|
|
cb(server, onDone);
|
|
} catch (e) {
|
|
onDone(e);
|
|
}
|
|
};
|
|
}
|
|
|
|
it(
|
|
"should work with .end(data)",
|
|
runWithServer((server, done) => {
|
|
const socket = new Socket()
|
|
.connect(server.port)
|
|
.on("ready", () => {
|
|
expect(socket).toBeDefined();
|
|
expect(socket.connecting).toBe(false);
|
|
})
|
|
.on("error", done)
|
|
.end(message);
|
|
}),
|
|
);
|
|
|
|
it(
|
|
"should work with .write(data).end()",
|
|
runWithServer((server, done) => {
|
|
const socket = new Socket()
|
|
.connect(server.port, () => {
|
|
expect(socket).toBeDefined();
|
|
expect(socket.connecting).toBe(false);
|
|
})
|
|
.on("error", done);
|
|
socket.write(message);
|
|
socket.end();
|
|
}),
|
|
);
|
|
|
|
it(
|
|
"should work with multiple .write()s",
|
|
runWithServer((server, done) => {
|
|
const socket = new Socket()
|
|
.connect(server.port, server.hostname, () => {
|
|
expect(socket).toBeDefined();
|
|
expect(socket.connecting).toBe(false);
|
|
})
|
|
.on("error", done);
|
|
const size = 10;
|
|
for (let i = 0; i < message.length; i += size) {
|
|
socket.write(message.slice(i, i + size));
|
|
}
|
|
socket.end();
|
|
}),
|
|
);
|
|
});
|
|
|
|
it("should handle connection error", done => {
|
|
var data = {};
|
|
connect(55555, () => {
|
|
done(new Error("Should not have connected"));
|
|
}).on("error", error => {
|
|
expect(error).toBeDefined();
|
|
expect(error.name).toBe("SystemError");
|
|
expect(error.message).toBe("Failed to connect");
|
|
done();
|
|
});
|
|
});
|