Skip to content

Commit 6defe2a

Browse files
committed
fix(test/bun): make byte stats work on Bun, refresh expired test cert
Two narrowly-scoped fixes that knock out concrete failure categories in the Bun e2e suite without touching Node behavior: 1. `count_target_bytes` now also accumulates bytes via passive 'data' listeners on the target socket and via a 'pipe'/'unpipe'-tracked listener on whatever's piped into it. Node continues to win on its own `socket.bytesRead`/`bytesWritten` counters (they're always at least as high as the manual tally, so `Math.max` keeps them). Bun 1.3 reports 0 on http client sockets — the manual counters now carry it. 2. Regenerated `test/e2e/ssl.crt` / `ssl.key` with a 100-year validity. The previous cert expired 2018-11-10; Node accepted it because the tests pass `rejectUnauthorized: false`, but Bun rejects expired certs strictly on the WS path and four `https-stress` / WS tests failed with "certificate has expired".
1 parent 5af20c6 commit 6defe2a

3 files changed

Lines changed: 120 additions & 53 deletions

File tree

src/utils/count_target_bytes.ts

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1+
import { Buffer } from 'node:buffer';
12
import type net from 'node:net';
3+
import type stream from 'node:stream';
24

35
const targetBytesWritten = Symbol('targetBytesWritten');
46
const targetBytesRead = Symbol('targetBytesRead');
57
const targets = Symbol('targets');
68
const calculateTargetStats = Symbol('calculateTargetStats');
79

10+
// Per-target manual counters. Used as a fallback when the underlying runtime
11+
// doesn't populate `socket.bytesRead` / `socket.bytesWritten` for the kind of
12+
// socket we got (e.g. Bun 1.3 currently reports 0 on http client sockets).
13+
const manualBytesRead = Symbol('manualBytesRead');
14+
const manualBytesWritten = Symbol('manualBytesWritten');
15+
816
type Stats = { bytesWritten: number | null, bytesRead: number | null };
917

1018
/**
@@ -20,23 +28,81 @@ interface Extras {
2028
[calculateTargetStats]: () => Stats;
2129
}
2230

31+
interface TargetExtras {
32+
[manualBytesRead]: number;
33+
[manualBytesWritten]: number;
34+
}
35+
36+
const byteLength = (chunk: Buffer | string): number => {
37+
return Buffer.isBuffer(chunk) ? chunk.length : Buffer.byteLength(chunk);
38+
};
39+
40+
const liveBytesRead = (target: SocketWithPreviousStats & TargetExtras): number => {
41+
const fromCounter = (target.bytesRead || 0) - (target.previousBytesRead || 0);
42+
return Math.max(fromCounter, target[manualBytesRead] || 0);
43+
};
44+
45+
const liveBytesWritten = (target: SocketWithPreviousStats & TargetExtras): number => {
46+
const fromCounter = (target.bytesWritten || 0) - (target.previousBytesWritten || 0);
47+
return Math.max(fromCounter, target[manualBytesWritten] || 0);
48+
};
49+
2350
export const countTargetBytes = (
2451
sourceSocket: net.Socket,
25-
target: SocketWithPreviousStats,
52+
targetSocket: SocketWithPreviousStats,
2653
registerCloseHandler?: (handler: () => void) => void,
2754
): void => {
2855
const source = sourceSocket as net.Socket & Extras;
56+
const target = targetSocket as SocketWithPreviousStats & TargetExtras;
2957

3058
source[targetBytesWritten] = source[targetBytesWritten] || 0;
3159
source[targetBytesRead] = source[targetBytesRead] || 0;
3260
source[targets] = source[targets] || new Set();
3361

3462
source[targets].add(target);
3563

36-
const closeHandler = () => {
37-
source[targetBytesWritten] += (target.bytesWritten - (target.previousBytesWritten || 0));
38-
source[targetBytesRead] += (target.bytesRead - (target.previousBytesRead || 0));
64+
// Manual byte counters via passive listeners. Zero overhead on Node.js
65+
// (the socket-level counters always win in `liveBytesRead/Written`) and
66+
// the only source of truth on Bun 1.3 where http client/server sockets
67+
// report `bytesRead`/`bytesWritten` as 0.
68+
target[manualBytesRead] = target[manualBytesRead] || 0;
69+
target[manualBytesWritten] = target[manualBytesWritten] || 0;
70+
71+
const onRead = (chunk: Buffer | string): void => {
72+
target[manualBytesRead] += byteLength(chunk);
73+
};
74+
target.on('data', onRead);
75+
76+
// Bytes _written_ to target equal bytes _emitted_ by whatever is piped
77+
// into it. Track via the source readable's 'data' events when the pipe is
78+
// wired up; detach when unpiped or on close.
79+
const trackedSources = new Map<stream.Readable, (chunk: Buffer | string) => void>();
80+
const onPipe = (src: stream.Readable): void => {
81+
const onSrcData = (chunk: Buffer | string): void => {
82+
target[manualBytesWritten] += byteLength(chunk);
83+
};
84+
trackedSources.set(src, onSrcData);
85+
src.on('data', onSrcData);
86+
};
87+
const onUnpipe = (src: stream.Readable): void => {
88+
const handler = trackedSources.get(src);
89+
if (handler) {
90+
src.off('data', handler);
91+
trackedSources.delete(src);
92+
}
93+
};
94+
target.on('pipe', onPipe);
95+
target.on('unpipe', onUnpipe);
96+
97+
const closeHandler = (): void => {
98+
source[targetBytesWritten] += liveBytesWritten(target);
99+
source[targetBytesRead] += liveBytesRead(target);
39100
source[targets].delete(target);
101+
target.off('data', onRead);
102+
target.off('pipe', onPipe);
103+
target.off('unpipe', onUnpipe);
104+
for (const [src, handler] of trackedSources) src.off('data', handler);
105+
trackedSources.clear();
40106
};
41107
if (!registerCloseHandler) {
42108
registerCloseHandler = (handler: () => void) => target.once('close', handler);
@@ -49,8 +115,8 @@ export const countTargetBytes = (
49115
let bytesRead = source[targetBytesRead];
50116

51117
for (const socket of source[targets]) {
52-
bytesWritten += (socket.bytesWritten - (socket.previousBytesWritten || 0));
53-
bytesRead += (socket.bytesRead - (socket.previousBytesRead || 0));
118+
bytesWritten += liveBytesWritten(socket as SocketWithPreviousStats & TargetExtras);
119+
bytesRead += liveBytesRead(socket as SocketWithPreviousStats & TargetExtras);
54120
}
55121

56122
return {

test/e2e/ssl.crt

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
-----BEGIN CERTIFICATE-----
2-
MIIDtTCCAp2gAwIBAgIJAOyaEf+jBkG4MA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
3-
BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
4-
aWRnaXRzIFB0eSBMdGQwHhcNMTcxMTEwMjAzNDM0WhcNMTgxMTEwMjAzNDM0WjBF
5-
MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
6-
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
7-
CgKCAQEAveAoPujCQ7RN2R09/Gp8cby6DyVOyob9VdiSJp8tTjWL0YmuGMdDa84n
8-
BbUbig8z2J5zvnce8/kwIGEIpe9Aho4pNHe9+q+BaLNWdFdazDO2rVjIuDNvylqB
9-
UZ3MeVY7uhVPIc7i4I8nh48dLIwCoo6bZuAKWjGNbOZ34iuvocixeLLjD9FPrfyS
10-
miFNvYYBIIE1cuG6v4c/6D58TNkon2dIWk4WdT8exRggSSkcn0gkfj0V7c4pbJsh
11-
xe2EihLEvT5CIL2oucQw0Nq1kzRBl9nIglrd7DO9CAYPlx3Kx3WoHG4MdibfbHbI
12-
WcaWbQcNTKOXMQa5bEsijzEd3uzxrQIDAQABo4GnMIGkMB0GA1UdDgQWBBR/xkww
13-
83cpqsT61bGnym/mFdbn9TB1BgNVHSMEbjBsgBR/xkww83cpqsT61bGnym/mFdbn
14-
9aFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV
15-
BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAOyaEf+jBkG4MAwGA1UdEwQF
16-
MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAJvr1vJO373jCTztVWqs1DxVUpC8TMAO
17-
zrv4Ry+1xcxowDkdyTNXhwfqshbrTEmfhl92zjNy4ZrYN/KN8kM+jg/fHbw5KNSd
18-
uNH2a74BuXVQR/fscFPsqmIWlsyrSCKpRUi0dLKo67ZrBcnUMYwBnxdQxu0hoB81
19-
B5ZDLptogoc3YN8+XmjqghKEx22hC1+RalQ4pI3n7ru73NLukLJb2c4kjK9AsZq3
20-
44Q5+RajPtFha+mTlRyh9ZCMWgjzqESfvGKHoIq2gcLGWN2FuqKS9SIU8TfdUoh4
21-
N7ABI4y4lktKuq/5AcHZXuXwLiuCG3rOGeb6zgUV0jXb79C0unDWbTs=
2+
MIIDuTCCAqGgAwIBAgIUb9W9BeBHuz1x8Xdwxn1XnyU8X/QwDQYJKoZIhvcNAQEL
3+
BQAwSzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFRlc3QxGTAXBgNVBAoMEHByb3h5
4+
LWNoYWluIHRlc3QxEjAQBgNVBAMMCWxvY2FsaG9zdDAgFw0yNjA1MTIyMDQzMzNa
5+
GA8yMTI2MDQxODIwNDMzM1owSzELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFRlc3Qx
6+
GTAXBgNVBAoMEHByb3h5LWNoYWluIHRlc3QxEjAQBgNVBAMMCWxvY2FsaG9zdDCC
7+
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALpi9p3osGEeS3plKCLzAXUA
8+
WxVo6X1AO/GmQEw5IG8y15GxBcyMG6BueAaV7/aMWWCHBfsEXkAKr6qGPhgqHuoP
9+
FFcYUvr52OKbfAQpN8XQ56kadKQ60hTWPqYTYulNh/sENDQkx2SWnFsTs/LVVtUX
10+
ltx7gwphbdLeCe7Yx42/fk4NI3Esg9okpvomtNSVuDTiwi/YG1WWLeCq5FIpZ3of
11+
2NClo86jWYctR/1KdyjpatCO7Bm2A1NTWblqMgxh4DDwUoIgxTaYgspARd0zT0Z/
12+
Q7OkynbNFfOz+rZpsXRWJ/TLyYUMoZ95MVeD1bVViPfjdU0G3A/lpjuoMyS0JbUC
13+
AwEAAaOBkjCBjzAdBgNVHQ4EFgQUloEOqBDUaVzabtl09fT/RcdIUdcwHwYDVR0j
14+
BBgwFoAUloEOqBDUaVzabtl09fT/RcdIUdcwDwYDVR0TAQH/BAUwAwEB/zA8BgNV
15+
HREENTAzgglsb2NhbGhvc3SCDmxvY2FsaG9zdC10ZXN0hwR/AAABhxAAAAAAAAAA
16+
AAAAAAAAAAABMA0GCSqGSIb3DQEBCwUAA4IBAQAzTtlx5FL8hGM5SN593C8tX9PO
17+
K4LpbzRZ0halkyC1yDAoSpibtRJhoAIa9zLyLzApjRNI7os5qRIetrZ13eJNluPv
18+
XJl0dDN+YuDz3adz1uOtWRkt96Oipf3ZImubDK0P5lEf6RA4SarOqAbk6ar84Owy
19+
7vGMGt0XLgQ+27RhKqnXeZDmUXBQdmWdDDqxpMCtKMBDY7NO08doa7BZeUevq3/C
20+
bnWCYhbAj0DiEWbMBXq3k9tuFGdVnl2ccxfwzx7UGORaQgoNePq4eyS55QrY6mho
21+
4YbrJsxruudm4cE2YiiNrxJzAdDZyRYa+hBO70y9lhfyVaZvdN0NMlvOi3OK
2222
-----END CERTIFICATE-----

test/e2e/ssl.key

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,28 @@
1-
-----BEGIN RSA PRIVATE KEY-----
2-
MIIEowIBAAKCAQEAveAoPujCQ7RN2R09/Gp8cby6DyVOyob9VdiSJp8tTjWL0Ymu
3-
GMdDa84nBbUbig8z2J5zvnce8/kwIGEIpe9Aho4pNHe9+q+BaLNWdFdazDO2rVjI
4-
uDNvylqBUZ3MeVY7uhVPIc7i4I8nh48dLIwCoo6bZuAKWjGNbOZ34iuvocixeLLj
5-
D9FPrfySmiFNvYYBIIE1cuG6v4c/6D58TNkon2dIWk4WdT8exRggSSkcn0gkfj0V
6-
7c4pbJshxe2EihLEvT5CIL2oucQw0Nq1kzRBl9nIglrd7DO9CAYPlx3Kx3WoHG4M
7-
dibfbHbIWcaWbQcNTKOXMQa5bEsijzEd3uzxrQIDAQABAoIBAQCp2ZgG1m3Y5LRy
8-
0I6/en5BvAJwQ/5cey6pmWb7t45ulMWzNkcPkUiFak9L8rtk376QOwXszmBY/IMJ
9-
o+N5lDETbJ39elPuqQrJHwvqXK4zVttF69L5u8F3sUhXOyJLNFGPXzp/UrNvD3/b
10-
6rC9Ra2hvpHTD/0Su5r4XJ3HKy8cN4ErQprmEJhKDYrP/Lp2uKDPwoxXiYcPOPKC
11-
CbgPLRrK+40GbCXtZVQgX0+nrJ/0syryNaA9wb1wHXfdWLyhvM2BGHz9gXtv2z1L
12-
3VvvbKpO2pygnLgUjLeJbk0/UI5Orz8MEAzGiq4wwiGqQZaGx/1C/WBlvnqnwuA5
13-
6vQQC7Q9AoGBAOoQZbir+W+ihkwIkTGb6pHnaPTAuslPSfR6RJbxGlv78wJ260KE
14-
foRKVdb06gQWwZwHniKA0GZeKBFNxSSdkyt8yZY84/w9KLFitX5HaBFoggroOWx+
15-
JCMuPDDnnlHm9REUzR2Zsl3KedNeV92JUDjx+ObUbexeK8wd0mLtqcO7AoGBAM+r
16-
mkJ4OrpTkPqVxkOim+LjMe/7EqX14QkPQrg3KzZmhyi7THOB5JMH+0/Bygrs1VP5
17-
OSEzWbPnjQ0GWoFEIw/iJbhvikhJPi4PXMrXIhreXcX7GezGp3nKHNf5vNpKAk4Z
18-
fPlCmHEBtcBHPygDPEODkTPz7B74QX6NX4ZrWCW3AoGAMg7Psm8VKYrYreonIzT1
19-
Nb8H81BEokkSx/ZeNOnbeVCo6B4GsnMjm6dKNG6snbNANN5sM3TZHQuGBi1bvDj3
20-
AJXvhvH+0DNEQKubpSYgW5i+NxbzMQDJObzpoovmkB2Uy9JnC62TN/vVkh7bK8Xy
21-
Ijudv8Auwh5hv4WhOQcbB4ECgYAqrG2PeRtATIm/JGXQYiq8TclmMeacGdF7RhqE
22-
tjl3/UuK0CoeljN9DyfSNNUqt44CqnTV4LJvKIawhXy1kWXPDr6HjswQnJRdbKS5
23-
vclxUf5c/4NNR2kEusaAjv4CsTCWEeC/a7LdjedmMn3E4B1TFkcRMO91UbhLpAtc
24-
GNTNMwKBgH954dHwNWbAXGJlqvP75MIuPdFNbi0TVKR8V9PbFg9eOVvWaeGGUr4I
25-
yUoDPTndfogpiT/PuXBy4IQ+BYNza0fTVcJzTD5vOgoeRYUDdL5SYAlnIhEVhw2U
26-
frBtb6JYt7jgP7HXyLG75+p+PVujxt20smxUKyLCfIqTNXeyIosW
27-
-----END RSA PRIVATE KEY-----
1+
-----BEGIN PRIVATE KEY-----
2+
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC6Yvad6LBhHkt6
3+
ZSgi8wF1AFsVaOl9QDvxpkBMOSBvMteRsQXMjBugbngGle/2jFlghwX7BF5ACq+q
4+
hj4YKh7qDxRXGFL6+djim3wEKTfF0OepGnSkOtIU1j6mE2LpTYf7BDQ0JMdklpxb
5+
E7Py1VbVF5bce4MKYW3S3gnu2MeNv35ODSNxLIPaJKb6JrTUlbg04sIv2BtVli3g
6+
quRSKWd6H9jQpaPOo1mHLUf9Snco6WrQjuwZtgNTU1m5ajIMYeAw8FKCIMU2mILK
7+
QEXdM09Gf0OzpMp2zRXzs/q2abF0Vif0y8mFDKGfeTFXg9W1VYj343VNBtwP5aY7
8+
qDMktCW1AgMBAAECggEASXwEDGz1wUyO6JIiWWkijW0W/CFxUQL2v0bTOdoaCg1r
9+
BVNcXHFu4Pk81CfgRH3ALTj+6CEoQaqU6K/lomRU7OYGGHKMIMxJsMopgoB3r0O2
10+
WisGistwEWwIpjSlfiMlthdJt7c6b9ObkKL7gwWOpxQWVBZUK08PXCBTnToVrzIA
11+
njrHcY+BKagCCT29QS3VggrkVQ9vFw29Nopc+vWtvTW6dAwOYtcdjPh0TuUWAoUm
12+
B/YDOdCxinTZL/iDmSS2AorTXyjwyni+9xB/Kc1wWdyJD25sUv4/amlLd/ctrNe0
13+
ThCQ36cHrGkm1/YQniOCnfXzt/jmSSmeKyGK5oRBPwKBgQDkv4Yc7Er+ikeeN0Qu
14+
XaGYU5x2IHn3gRH+BXs/hV03r5LGmG4BwDsjN9xLZl+wEsCj2agfdpZ6MBL/tir5
15+
Cv38wSO8BNPr/5tm/ReNvtq6xVYrSfggPqhxOgVCx+4CFHWT/nsGaaORT/U7tI/k
16+
DSSziRvzFy7qqNVluJGGrojWOwKBgQDQl3mg6EaEgL3Ij9e3S6k6+9QF4mETe4l6
17+
3pp/f9Av+wZYPpU6C9sXzFiycl+lFRFf7aRzXFQbe5gtTRE0qMrh4jcB2/rgrl29
18+
LglxfRKOUbQro5XKXFcW4pqpWtKFCKVpp1Ulm3LRzvmJXTaqpD3EA+oLiqmCDKRQ
19+
dL6+GMIEzwKBgBg9l5e/Dp90xewlTStgrrw2uBDoliQ9YEu8BviPSHabO4GiK54x
20+
4dJ0m/q9iYxeIF38tc1HwuCF8a15f4pOuOWtDf1hwZdzyeMbFQDnZcR/HweNWicI
21+
nM8K5/3QtA8yXddmE2F1lmjSwVknZEw1fFsuP3D+VvF1HNAfxAQywLt7AoGBAI+4
22+
Pnpqb+Pt3FVrHoNRY0mbp4tiXeaRkLkS1TqR8vyMJeP5QtJaxttP1bEl8taIfI8u
23+
6sb9T4ocD07vMbKpthgKyEHEssfJ/BZTuPfz6CwdCVmj/ZoPI4ZGHbAgPrqgqW/x
24+
dk5SG7uJsw89JWRPg6sh00megYp0cWZp+d56qnurAoGAD9H2P1U57mOamCXQ7CXp
25+
V7dTz0g0CtL27vv0oyuALO7KZkQ1x8VPH/SyeHsrhAILTyHPBNQlQB+0yqhiu4bM
26+
vSSf53h6krtPvR/CyBhHOOkZY3JaMHoHeEpl09ItkEgzLDlQvRE+RDWIQxC8wfK3
27+
X1EXRrG8H6/refNFZizb/5M=
28+
-----END PRIVATE KEY-----

0 commit comments

Comments
 (0)