aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorGravatar Ciro Spaciari <ciro.spaciari@gmail.com> 2023-04-07 08:02:05 -0300
committerGravatar GitHub <noreply@github.com> 2023-04-07 04:02:05 -0700
commit6baedd27bc6f0f271249a5b332d3212254909141 (patch)
tree22b8f7a3a847bb1ea5df53e799ec331f3b737b8b /test
parent5465a3980a915ec1b3b20a8c445cdbaa49f8924f (diff)
downloadbun-6baedd27bc6f0f271249a5b332d3212254909141.tar.gz
bun-6baedd27bc6f0f271249a5b332d3212254909141.tar.zst
bun-6baedd27bc6f0f271249a5b332d3212254909141.zip
feat(tls.Server) basic support (cert, key, rejectUnauthorized, requestCert, ca) #2412 (#2552)
* cherry picked * add StringOrBuffer parameter * Format and adds types * update uws * fix tests * more types * fix typing * add timeouts, clean some stuff * move tests to describe * fixes SSL hostname when Host is provided * cleanup on tests * change 127.0.0.1 to 0.0.0.0 * try another listening parameter * test timings and update uws * remove unnecessary comment * move listening event around * always await Bun.connect * do not fail if the tests already passed when using Bun.connect * regenerate classes * undo generated classes * generate classes * fix merge --------- Co-authored-by: cirospaciari <cirospaciari@MiWiFi-RA82-srv.cirospaciari>
Diffstat (limited to 'test')
-rw-r--r--test/js/node/tls/fixtures/rsa_cert.crt24
-rw-r--r--test/js/node/tls/fixtures/rsa_private.pem27
-rw-r--r--test/js/node/tls/fixtures/rsa_private_encrypted.pem30
-rw-r--r--test/js/node/tls/node-tls-server.test.ts627
4 files changed, 708 insertions, 0 deletions
diff --git a/test/js/node/tls/fixtures/rsa_cert.crt b/test/js/node/tls/fixtures/rsa_cert.crt
new file mode 100644
index 000000000..3bcf90e2a
--- /dev/null
+++ b/test/js/node/tls/fixtures/rsa_cert.crt
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEAjCCAuqgAwIBAgIUVaZoDmyyS79pzShST5zhsKbvWR0wDQYJKoZIhvcNAQEL
+BQAwgbAxCzAJBgNVBAYTAlVLMRQwEgYDVQQIDAtBY2tuYWNrIEx0ZDETMBEGA1UE
+BwwKUmh5cyBKb25lczEQMA4GA1UECgwHbm9kZS5qczEdMBsGA1UECwwUVGVzdCBU
+TFMgQ2VydGlmaWNhdGUxFDASBgNVBAsMC0VuZ2luZWVyaW5nMRIwEAYDVQQDDAls
+b2NhbGhvc3QxGzAZBgkqhkiG9w0BCQEWDGFsZXhAYXViLmRldjAgFw0yMjA5MDMx
+NDQ2NTRaGA8yMjk2MDYxNzE0NDY1NFowgbAxCzAJBgNVBAYTAlVLMRQwEgYDVQQI
+DAtBY2tuYWNrIEx0ZDETMBEGA1UEBwwKUmh5cyBKb25lczEQMA4GA1UECgwHbm9k
+ZS5qczEdMBsGA1UECwwUVGVzdCBUTFMgQ2VydGlmaWNhdGUxFDASBgNVBAsMC0Vu
+Z2luZWVyaW5nMRIwEAYDVQQDDAlsb2NhbGhvc3QxGzAZBgkqhkiG9w0BCQEWDGFs
+ZXhAYXViLmRldjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALfcWIiK
+J7HAt78/wNnHkeyoWWZQ7v+W8nud5wlU3Cp1ndrHmOlAHSnq7F+p46/Nw3eTlXtQ
+Vv8Cb6eRI1kwBmGxbMJTZng+OHnRBjPd/Qei6vv/IgZK04vJhjeGAsrYrxNuGCNA
++F2TD35C0qWm9svx8uA40CgatU4WdFAZyvvSIV9+ybv2aBmEpUyBiIc8momAYe8K
+2QaD3MyBLunrf5DdlZ520VLZGExfe4IHL+YfoQ6VEI0FtGYDjHE3PJ/kZBqSLdP4
+jP204yN08/4LBXYuoR3KWYG6KTy+t9NveogcsooEAjyVc3brBa0DeQ3gvs0/5xsq
+UJGWpy2+GbKUsfUCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsF
+AAOCAQEALcyUnR9nUaKtYwomY5nf7GzaVLGiprbN2irZgfrbdBRIbNGTaOOzzoDW
+31pmrppYT5P8e1ORN+eHaD7h1mVhT6b2tix3xPxKasuu6iYYGRRu4SiKEfHKwYtU
+g/Q/eFI1MquhitOYEZA7C/6TK6Stx4ot5sNPAmgbYRLz6ljUCMeGHM/JHIMlrAbt
+2R3Wyo0UWQINqAT11miJcL0a9UCGScCZxmz90Hs+uk6MtiY8kNSXHL5So4tg7qFz
+nFWSMhIu+1f4hbxD9inOTJczzw1iCXuWRe3+rvqPDxJyHGMiriiXrdBY6CXa20jx
+P1lIqHSThAkWfOgOhmQ0OdvSWlKvNA==
+-----END CERTIFICATE-----
diff --git a/test/js/node/tls/fixtures/rsa_private.pem b/test/js/node/tls/fixtures/rsa_private.pem
new file mode 100644
index 000000000..215e5cc51
--- /dev/null
+++ b/test/js/node/tls/fixtures/rsa_private.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAt9xYiIonscC3vz/A2ceR7KhZZlDu/5bye53nCVTcKnWd2seY
+6UAdKersX6njr83Dd5OVe1BW/wJvp5EjWTAGYbFswlNmeD44edEGM939B6Lq+/8i
+BkrTi8mGN4YCytivE24YI0D4XZMPfkLSpab2y/Hy4DjQKBq1ThZ0UBnK+9IhX37J
+u/ZoGYSlTIGIhzyaiYBh7wrZBoPczIEu6et/kN2VnnbRUtkYTF97ggcv5h+hDpUQ
+jQW0ZgOMcTc8n+RkGpIt0/iM/bTjI3Tz/gsFdi6hHcpZgbopPL630296iByyigQC
+PJVzdusFrQN5DeC+zT/nGypQkZanLb4ZspSx9QIDAQABAoIBAQCS2erYu8gyoGPi
+3E/zYgQ6ishFAZWzDWSFubwD5wSm4SSAzvViL/RbO6kqS25xR569DmLRiHzD17VI
+mJMsNECUnPrqR2TL256OJZaXrNHh3I1lUwVhEzjeKMsL4/ys+d70XPXoiocVblVs
+moDXEIGEqa48ywPvVE3Fngeuxrsq3/GCVBNiwtt0YjAOZxmKEh31UZdHO+YI+wNF
+/Z8KQCPscN5HGlR0SIQOlqMANz49aKStrevdvjS1UcpabzDEkuK84g3saJhcpAhb
+pGFmAf5GTjkkhE0rE1qDF15dSqrKGfCFtOjUeK17SIEN7E322ChmTReZ1hYGfoSV
+cdFntUINAoGBAPFKL5QeJ6wZu8R/ru11wTG6sQA0Jub2hGccPXpbnPrT+3CACOLI
+JTCLy/xTKW3dqRHj/wZEe+jUw88w7jwGb1BkWr4BI8tDvY9jQLP1jyuLWRfrxXbp
+4Z0oeBBwBeCI/ZG7FIvdDTqWxn1aj3Tmh6s4ByqEdtwrrrJPcBUNl01fAoGBAMMR
+3RGE/ca6X6xz6kgUD6TtHVhiiRJK1jm/u+q0n7i/MBkeDgTZkHYS7lPc0yIdtqaI
+Plz5yzwHnAvuMrv8LSdkjwioig2yQa3tAij8kXxqs7wN5418DMV2s1OJBrPthYPs
+bv4im2iI8V63JQS4ZMYQbckq8ABYccTpOnxXDy0rAoGBAKkvzHa+QjERhjB9GyoT
+1FhLQIsVBmYSWrp1+cGO9V6HPxoeHJzvm+wTSf/uS/FmaINL6+j4Ii4a6gWgmJts
+I6cqBtqNsAx5vjQJczf8KdxthBYa0sXTrsfktXNJKUXMqIgDtp9vazQ2vozs8AQX
+FPAAhD3SzgkJdCBBRSTt97ZfAoGAWAziKpxLKL7LnL4dzDcx8JIPIuwnTxh0plCD
+dCffyLaT8WJ9lXbXHFTjOvt8WfPrlDP/Ylxmfkw5BbGZOP1VLGjZn2DkH9aMiwNm
+bDXFPdG0G3hzQovx/9fajiRV4DWghLHeT9wzJfZabRRiI0VQR472300AVEeX4vgb
+rDBn600CgYEAk7czBCT9rHn/PNwCa17hlTy88C4vXkwbz83Oa+aX5L4e5gw5lhcR
+2ZuZHLb2r6oMt9rlD7EIDItSs+u21LOXWPTAlazdnpYUyw/CzogM/PN+qNwMRXn5
+uXFFhmlP2mVg2EdELTahXch8kWqHaCSX53yvqCtRKu/j76V31TfQZGM=
+-----END RSA PRIVATE KEY-----
diff --git a/test/js/node/tls/fixtures/rsa_private_encrypted.pem b/test/js/node/tls/fixtures/rsa_private_encrypted.pem
new file mode 100644
index 000000000..f1914289e
--- /dev/null
+++ b/test/js/node/tls/fixtures/rsa_private_encrypted.pem
@@ -0,0 +1,30 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: AES-256-CBC,DB3D20E60E8FDC3356BD79712FF8EF7E
+
+K+vu0U3IFTJBBi6zW5Zng80O1jXq/ZmlOFs/j/SQpPwfW1Do9i/Dwa7ntBlTwrCm
+sd3IIPgu2ikfLwxvbxsZN540oCaCqaZ/bmmyzH3MyVDA9MllUu+X8+Q3ATzcYa9R
+U5XfF5DAXsSRnstCbmKagWVQpO0oX8k3ratfny6Ixq86Y82tK8+o5YiBFq1kqa+9
+4yat7IWQbqV5ifUtUPCHZwEqBt+WKazX05BqERjkckHdpfaDrBvSSPXTwoLm6uRR
+ktkUVpO4tHMZ4VlcTfFtpz8gdYYod0nM6vz26hvbESHSwztSgMhmKdsE5eqmYfgu
+F4WkEN4bqAiPjKK3jnUKPt/vg2oKYFQlVYFl9QnBjiRqcQTi3e9lwn1hI7uoMb6g
+HuaCc57JJHPN/ZLP3ts4ZxFbwUjTGioh5Zh6WozG3L3+Ujwq/sDrAskRyzdcuP7I
+Rs3oLbHY03OHyg8IbxR5Iu89l6FLqnR45yvbxXtZ7ImGOPM5Z9pB1CzDhGDx2F6g
+J/Kf/7ZF2DmYUVbVKDfESEDhRfuMAVzhasDPTRqipSA5QvJVQY+J/6QDPrNNmHVB
+4e4ouHIDWERUf0t1Be7THvP3X8OJozj2HApzqa5ZCaJDo8eaL8TCD5uH75ID5URJ
+VscGHaUXT8/sxfHi1x8BibW5W5J/akFsnrnJU/1BZgGznIxjf5tKfHGppSIVdlKP
+3ghYNmEIFPNJ6cxuUA0D2IOV4uO3FTCU6seIzvJhYkmXnticcZYGtmGxXKrodtzS
+J1YuaNkkO/YRZah285lQ6QCIhCFo4Oa4ILjgoTQISuw7nQj5ESyncauzLUBXKX0c
+XDUej64KNTvVF9UXdG48fYvNmSZWCnTye4UmPu17FmwpVra38U+EdoLyWyMIAI5t
+rP6Hhgc9BxOo41Im9QpTcAPfKAknP8Rbm3ACJG5T9FKq/c29d1E//eFR6SL51e/a
+yWdCgJN/FJOAX60+erPwoVoRFEttAeDPkklgFGdc8F4LIYAig9gEZ92ykFFz3fWz
+jIcUVLrL+IokFbPVUBoMihqVyMQsWH+5Qq9wjxf6EDIf0BVtm9U4BJoOkPStFIfF
+Kof7OVv7izyL8R/GIil9VQs9ftwkIUPeXx2Hw0bE3HJ3C8K4+mbLg3tKhGnBDU5Z
+Xm5mLHoCRBa3ZRFWZtigX7POszdLAzftYo8o65Be4OtPS+tQAORk9gHsXATv7dDB
+OGw61x5KA55LHVHhWaRvu3J8E7nhxw0q/HskyZhDC+Y+Xs6vmQSb4nO4ET4NYX1P
+m3PMdgGoqRDJ2jZw4eoQdRKCM0EHSepSAYpO1tcAXhPZS4ITogoRgPpVgOebEQUL
+nKNeNu/BxMSH/IH15jjDLF3TiEoguF9xdTaCxIBzE1SFpVO0u9m9vXpWdPThVgsb
+VcEI487p7v9iImP3BYPT8ZYvytC26EH0hyOrwhahTvTb4vXghkLIyvPUg1lZHc6e
+aPHb2AzYAHLnp/ehDQGKWrCOJ1JE2vBv8ZkLa+XZo7YASXBRZitPOMlvykEyzxmR
+QAmNhKGvFmeM2mmHAp0aC03rgF3lxNsXQ1CyfEdq3UV9ReSnttq8gtrJfCwxV+wY
+-----END RSA PRIVATE KEY-----
diff --git a/test/js/node/tls/node-tls-server.test.ts b/test/js/node/tls/node-tls-server.test.ts
new file mode 100644
index 000000000..a82f8cde2
--- /dev/null
+++ b/test/js/node/tls/node-tls-server.test.ts
@@ -0,0 +1,627 @@
+import { createServer, Server, TLSSocket } from "tls";
+import { realpathSync, readFileSync } from "fs";
+import { tmpdir } from "os";
+import { join } from "path";
+import { createTest } from "node-harness";
+import { AddressInfo } from "net";
+
+const { describe, expect, it, createCallCheckCtx } = createTest(import.meta.path);
+
+const passKeyFile = join(import.meta.dir, "fixtures", "rsa_private_encrypted.pem");
+const passKey = readFileSync(passKeyFile);
+const rawKeyFile = join(import.meta.dir, "fixtures", "rsa_private.pem");
+const rawKey = readFileSync(rawKeyFile);
+const certFile = join(import.meta.dir, "fixtures", "rsa_cert.crt");
+const cert = readFileSync(certFile);
+
+const COMMON_CERT: object = {
+ cert: "-----BEGIN CERTIFICATE-----\nMIIDXTCCAkWgAwIBAgIJAKLdQVPy90jjMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV\nBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\naWRnaXRzIFB0eSBMdGQwHhcNMTkwMjAzMTQ0OTM1WhcNMjAwMjAzMTQ0OTM1WjBF\nMQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50\nZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\nCgKCAQEA7i7IIEdICTiSTVx+ma6xHxOtcbd6wGW3nkxlCkJ1UuV8NmY5ovMsGnGD\nhJJtUQ2j5ig5BcJUf3tezqCNW4tKnSOgSISfEAKvpn2BPvaFq3yx2Yjz0ruvcGKp\nDMZBXmB/AAtGyN/UFXzkrcfppmLHJTaBYGG6KnmU43gPkSDy4iw46CJFUOupc51A\nFIz7RsE7mbT1plCM8e75gfqaZSn2k+Wmy+8n1HGyYHhVISRVvPqkS7gVLSVEdTea\nUtKP1Vx/818/HDWk3oIvDVWI9CFH73elNxBkMH5zArSNIBTehdnehyAevjY4RaC/\nkK8rslO3e4EtJ9SnA4swOjCiqAIQEwIDAQABo1AwTjAdBgNVHQ4EFgQUv5rc9Smm\n9c4YnNf3hR49t4rH4yswHwYDVR0jBBgwFoAUv5rc9Smm9c4YnNf3hR49t4rH4ysw\nDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEATcL9CAAXg0u//eYUAlQa\nL+l8yKHS1rsq1sdmx7pvsmfZ2g8ONQGfSF3TkzkI2OOnCBokeqAYuyT8awfdNUtE\nEHOihv4ZzhK2YZVuy0fHX2d4cCFeQpdxno7aN6B37qtsLIRZxkD8PU60Dfu9ea5F\nDDynnD0TUabna6a0iGn77yD8GPhjaJMOz3gMYjQFqsKL252isDVHEDbpVxIzxPmN\nw1+WK8zRNdunAcHikeoKCuAPvlZ83gDQHp07dYdbuZvHwGj0nfxBLc9qt90XsBtC\n4IYR7c/bcLMmKXYf0qoQ4OzngsnPI5M+v9QEHvYWaKVwFY4CTcSNJEwfXw+BAeO5\nOA==\n-----END CERTIFICATE-----",
+ key: "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDuLsggR0gJOJJN\nXH6ZrrEfE61xt3rAZbeeTGUKQnVS5Xw2Zjmi8ywacYOEkm1RDaPmKDkFwlR/e17O\noI1bi0qdI6BIhJ8QAq+mfYE+9oWrfLHZiPPSu69wYqkMxkFeYH8AC0bI39QVfOSt\nx+mmYsclNoFgYboqeZTjeA+RIPLiLDjoIkVQ66lznUAUjPtGwTuZtPWmUIzx7vmB\n+pplKfaT5abL7yfUcbJgeFUhJFW8+qRLuBUtJUR1N5pS0o/VXH/zXz8cNaTegi8N\nVYj0IUfvd6U3EGQwfnMCtI0gFN6F2d6HIB6+NjhFoL+QryuyU7d7gS0n1KcDizA6\nMKKoAhATAgMBAAECggEAd5g/3o1MK20fcP7PhsVDpHIR9faGCVNJto9vcI5cMMqP\n6xS7PgnSDFkRC6EmiLtLn8Z0k2K3YOeGfEP7lorDZVG9KoyE/doLbpK4MfBAwBG1\nj6AHpbmd5tVzQrnNmuDjBBelbDmPWVbD0EqAFI6mphXPMqD/hFJWIz1mu52Kt2s6\n++MkdqLO0ORDNhKmzu6SADQEcJ9Suhcmv8nccMmwCsIQAUrfg3qOyqU4//8QB8ZM\njosO3gMUesihVeuF5XpptFjrAliPgw9uIG0aQkhVbf/17qy0XRi8dkqXj3efxEDp\n1LSqZjBFiqJlFchbz19clwavMF/FhxHpKIhhmkkRSQKBgQD9blaWSg/2AGNhRfpX\nYq+6yKUkUD4jL7pmX1BVca6dXqILWtHl2afWeUorgv2QaK1/MJDH9Gz9Gu58hJb3\nymdeAISwPyHp8euyLIfiXSAi+ibKXkxkl1KQSweBM2oucnLsNne6Iv6QmXPpXtro\nnTMoGQDS7HVRy1on5NQLMPbUBQKBgQDwmN+um8F3CW6ZV1ZljJm7BFAgNyJ7m/5Q\nYUcOO5rFbNsHexStrx/h8jYnpdpIVlxACjh1xIyJ3lOCSAWfBWCS6KpgeO1Y484k\nEYhGjoUsKNQia8UWVt+uWnwjVSDhQjy5/pSH9xyFrUfDg8JnSlhsy0oC0C/PBjxn\nhxmADSLnNwKBgQD2A51USVMTKC9Q50BsgeU6+bmt9aNMPvHAnPf76d5q78l4IlKt\nwMs33QgOExuYirUZSgjRwknmrbUi9QckRbxwOSqVeMOwOWLm1GmYaXRf39u2CTI5\nV9gTMHJ5jnKd4gYDnaA99eiOcBhgS+9PbgKSAyuUlWwR2ciL/4uDzaVeDQKBgDym\nvRSeTRn99bSQMMZuuD5N6wkD/RxeCbEnpKrw2aZVN63eGCtkj0v9LCu4gptjseOu\n7+a4Qplqw3B/SXN5/otqPbEOKv8Shl/PT6RBv06PiFKZClkEU2T3iH27sws2EGru\nw3C3GaiVMxcVewdg1YOvh5vH8ZVlxApxIzuFlDvnAoGAN5w+gukxd5QnP/7hcLDZ\nF+vesAykJX71AuqFXB4Wh/qFY92CSm7ImexWA/L9z461+NKeJwb64Nc53z59oA10\n/3o2OcIe44kddZXQVP6KTZBd7ySVhbtOiK3/pCy+BQRsrC7d71W914DxNWadwZ+a\njtwwKjDzmPwdIXDSQarCx0U=\n-----END PRIVATE KEY-----",
+ passphrase: "1234",
+};
+
+const socket_domain = join(realpathSync(tmpdir()), "node-tls-server.sock");
+
+describe("tls.createServer listen", () => {
+ it("should throw when no port or path when using options", done => {
+ expect(() => createServer(COMMON_CERT).listen({ exclusive: true })).toThrow(
+ 'The argument \'options\' must have the property "port" or "path". Received {"exclusive":true}',
+ );
+ done();
+ });
+
+ it("should listen on IPv6 by default", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ const server: Server = createServer(COMMON_CERT);
+ let timeout: Timer;
+ const closeAndFail = () => {
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall()();
+ };
+ server.on("error", closeAndFail);
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(
+ 0,
+ mustCall(() => {
+ const address = server.address() as AddressInfo;
+ expect(address.address).toStrictEqual("::");
+ //system should provide an port when 0 or no port is passed
+ expect(address.port).toBeGreaterThan(100);
+ expect(address.family).toStrictEqual("IPv6");
+ server.close();
+ done();
+ }),
+ );
+ });
+
+ it("should listen on IPv4", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ const server: Server = createServer(COMMON_CERT);
+
+ let timeout: Timer;
+ const closeAndFail = () => {
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall()();
+ };
+ server.on("error", closeAndFail);
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(
+ 0,
+ "0.0.0.0",
+ mustCall(() => {
+ const address = server.address() as AddressInfo;
+ expect(address.address).toStrictEqual("0.0.0.0");
+ //system should provide an port when 0 or no port is passed
+ expect(address.port).toBeGreaterThan(100);
+ expect(address.family).toStrictEqual("IPv4");
+ server.close();
+ done();
+ }),
+ );
+ });
+
+ it("should call listening", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ const server: Server = createServer(COMMON_CERT);
+
+ let timeout: Timer;
+ const closeAndFail = () => {
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall()();
+ };
+
+ server.on("error", closeAndFail).on(
+ "listening",
+ mustCall(() => {
+ clearTimeout(timeout);
+ server.close();
+ done();
+ }),
+ );
+
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(0, "0.0.0.0");
+ });
+
+ it("should listen on localhost", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ const server: Server = createServer(COMMON_CERT);
+
+ let timeout: Timer;
+ const closeAndFail = () => {
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall()();
+ };
+ server.on("error", closeAndFail);
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(
+ 0,
+ "::1",
+ mustCall(() => {
+ const address = server.address() as AddressInfo;
+ expect(address.address).toStrictEqual("::1");
+ //system should provide an port when 0 or no port is passed
+ expect(address.port).toBeGreaterThan(100);
+ expect(address.family).toStrictEqual("IPv6");
+ server.close();
+ done();
+ }),
+ );
+ });
+
+ it("should listen on localhost", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ const server: Server = createServer(COMMON_CERT);
+
+ let timeout: Timer;
+ const closeAndFail = () => {
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall()();
+ };
+ server.on("error", closeAndFail);
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(
+ 0,
+ "::1",
+ mustCall(() => {
+ const address = server.address() as AddressInfo;
+ expect(address.address).toStrictEqual("::1");
+ expect(address.family).toStrictEqual("IPv6");
+ server.close();
+ done();
+ }),
+ );
+ });
+
+ it("should listen without port or host", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ const server: Server = createServer(COMMON_CERT);
+
+ let timeout: Timer;
+ const closeAndFail = () => {
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall()();
+ };
+ server.on("error", closeAndFail);
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(
+ mustCall(() => {
+ const address = server.address() as AddressInfo;
+ expect(address.address).toStrictEqual("::");
+ //system should provide an port when 0 or no port is passed
+ expect(address.port).toBeGreaterThan(100);
+ expect(address.family).toStrictEqual("IPv6");
+ server.close();
+ done();
+ }),
+ );
+ });
+
+ it("should listen on the correct port", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ const server: Server = createServer(COMMON_CERT);
+
+ let timeout: Timer;
+ const closeAndFail = () => {
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall()();
+ };
+ server.on("error", closeAndFail);
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(
+ 49027,
+ mustCall(() => {
+ const address = server.address() as AddressInfo;
+ expect(address.address).toStrictEqual("::");
+ expect(address.port).toStrictEqual(49027);
+ expect(address.family).toStrictEqual("IPv6");
+ server.close();
+ done();
+ }),
+ );
+ });
+
+ it("should listen on the correct port with IPV4", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ const server: Server = createServer(COMMON_CERT);
+
+ let timeout: Timer;
+ const closeAndFail = () => {
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall()();
+ };
+ server.on("error", closeAndFail);
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(
+ 49026,
+ "0.0.0.0",
+ mustCall(() => {
+ const address = server.address() as AddressInfo;
+ expect(address.address).toStrictEqual("0.0.0.0");
+ expect(address.port).toStrictEqual(49026);
+ expect(address.family).toStrictEqual("IPv4");
+ server.close();
+ done();
+ }),
+ );
+ });
+
+ it("should listen on unix domain socket", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ const server: Server = createServer(COMMON_CERT);
+
+ let timeout: Timer;
+ const closeAndFail = () => {
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall()();
+ };
+ server.on("error", closeAndFail);
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(
+ socket_domain,
+ mustCall(() => {
+ const address = server.address();
+ expect(address).toStrictEqual(socket_domain);
+ server.close();
+ done();
+ }),
+ );
+ });
+
+ it("should not listen with wrong password", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ const server: Server = createServer({
+ key: passKey,
+ passphrase: "invalid",
+ cert: cert,
+ });
+
+ server.on("error", mustCall());
+ let timeout: Timer;
+ function closeAndFail() {
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall()();
+ }
+
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(0, "0.0.0.0", closeAndFail);
+ });
+
+ it("should not listen without cert", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ const server: Server = createServer({
+ key: passKey,
+ passphrase: "invalid",
+ });
+
+ server.on("error", mustCall());
+
+ let timeout: Timer;
+ function closeAndFail() {
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall()();
+ }
+
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(0, "0.0.0.0", closeAndFail);
+ });
+
+ it("should not listen without password", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ const server: Server = createServer({
+ key: passKey,
+ cert: cert,
+ });
+
+ server.on("error", mustCall());
+
+ let timeout: Timer;
+ function closeAndFail() {
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall()();
+ }
+
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(0, "0.0.0.0", closeAndFail);
+ });
+});
+
+describe("tls.createServer events", () => {
+ it("should receive data", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+ let timeout: Timer;
+ let client: any = null;
+ let is_done = false;
+ const onData = mustCall(data => {
+ is_done = true;
+ clearTimeout(timeout);
+ server.close();
+ expect(data.byteLength).toBe(5);
+ expect(data.toString("utf8")).toBe("Hello");
+ done();
+ });
+
+ const server: Server = createServer(COMMON_CERT, (socket: TLSSocket) => {
+ socket.on("data", onData);
+ });
+
+ const closeAndFail = () => {
+ if (is_done) return;
+ clearTimeout(timeout);
+ server.close();
+ client?.end();
+ mustNotCall("no data received")();
+ };
+
+ server.on("error", closeAndFail);
+
+ //should be faster than 100ms
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(
+ mustCall(async () => {
+ const address = server.address() as AddressInfo;
+ client = await Bun.connect({
+ tls: true,
+ hostname: address.address,
+ port: address.port,
+ socket: {
+ data(socket) {},
+ handshake(socket, success, verifyError) {
+ if (socket.write("Hello")) {
+ socket.end();
+ }
+ },
+ connectError: closeAndFail, // connection failed
+ },
+ }).catch(closeAndFail);
+ }),
+ );
+ });
+
+ it("should call end", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+ let timeout: Timer;
+ let is_done = false;
+ const onEnd = mustCall(() => {
+ is_done = true;
+ clearTimeout(timeout);
+ server.close();
+ done();
+ });
+
+ const server: Server = createServer(COMMON_CERT, (socket: TLSSocket) => {
+ socket.on("end", onEnd);
+ socket.end();
+ });
+
+ const closeAndFail = () => {
+ if (is_done) return;
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall("end not called")();
+ };
+ server.on("error", closeAndFail);
+
+ //should be faster than 100ms
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(
+ mustCall(async () => {
+ const address = server.address() as AddressInfo;
+ await Bun.connect({
+ tls: true,
+ hostname: address.address,
+ port: address.port,
+ socket: {
+ data(socket) {},
+ open(socket) {},
+ connectError: closeAndFail, // connection failed
+ },
+ }).catch(closeAndFail);
+ }),
+ );
+ });
+
+ it("should call close", done => {
+ let closed = false;
+ const server: Server = createServer(COMMON_CERT);
+ server.listen().on("close", () => {
+ closed = true;
+ });
+ server.close();
+ expect(closed).toBe(true);
+ done();
+ });
+
+ it("should call connection and drop", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ let timeout: Timer;
+ let is_done = false;
+ const server = createServer();
+ let maxClients = 2;
+ server.maxConnections = maxClients - 1;
+
+ const closeAndFail = () => {
+ if (is_done) return;
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall("drop not called")();
+ };
+
+ //should be faster than 100ms
+ timeout = setTimeout(closeAndFail, 100);
+ let connection_called = false;
+ server
+ .on(
+ "connection",
+ mustCall(() => {
+ connection_called = true;
+ }),
+ )
+ .on(
+ "drop",
+ mustCall(data => {
+ is_done = true;
+ server.close();
+ clearTimeout(timeout);
+ expect(data.localPort).toBeDefined();
+ expect(data.remotePort).toBeDefined();
+ expect(data.remoteFamily).toBeDefined();
+ expect(data.localFamily).toBeDefined();
+ expect(data.localAddress).toBeDefined();
+ expect(connection_called).toBe(true);
+ done();
+ }),
+ )
+ .listen(async () => {
+ const address = server.address() as AddressInfo;
+
+ async function spawnClient() {
+ await Bun.connect({
+ tls: true,
+ port: address?.port,
+ hostname: address?.address,
+ socket: {
+ data(socket) {},
+ handshake(socket, success, verifyError) {},
+ open(socket) {
+ socket.end();
+ },
+ },
+ });
+ }
+
+ const promises = [];
+ for (let i = 0; i < maxClients; i++) {
+ promises.push(spawnClient());
+ }
+ await Promise.all(promises).catch(closeAndFail);
+ });
+ });
+
+ it("should call error", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ let timeout: Timer;
+ const server: Server = createServer(COMMON_CERT);
+
+ const closeAndFail = () => {
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall("error not called")();
+ };
+
+ //should be faster than 100ms
+ timeout = setTimeout(closeAndFail, 100);
+
+ server
+ .on(
+ "error",
+ mustCall(err => {
+ server.close();
+ clearTimeout(timeout);
+ expect(err).toBeDefined();
+ done();
+ }),
+ )
+ .listen(123456);
+ });
+
+ it("should call abort with signal", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+
+ const controller = new AbortController();
+ let timeout: Timer;
+ const server = createServer(COMMON_CERT);
+
+ const closeAndFail = () => {
+ clearTimeout(timeout);
+ server.close();
+ mustNotCall("close not called")();
+ };
+
+ //should be faster than 100ms
+ timeout = setTimeout(closeAndFail, 100);
+
+ server
+ .on(
+ "close",
+ mustCall(() => {
+ clearTimeout(timeout);
+ done();
+ }),
+ )
+ .listen({ port: 0, signal: controller.signal }, () => {
+ controller.abort();
+ });
+ });
+
+ it("should echo data", done => {
+ const { mustCall, mustNotCall } = createCallCheckCtx(done);
+ let timeout: Timer;
+ let client: any = null;
+ const server: Server = createServer(COMMON_CERT, (socket: TLSSocket) => {
+ socket.pipe(socket);
+ });
+ let is_done = false;
+ const closeAndFail = () => {
+ if (is_done) return;
+ clearTimeout(timeout);
+ server.close();
+ client?.end();
+ mustNotCall("no data received")();
+ };
+
+ server.on("error", closeAndFail);
+
+ //should be faster than 100ms
+ timeout = setTimeout(closeAndFail, 100);
+
+ server.listen(
+ mustCall(async () => {
+ const address = server.address() as AddressInfo;
+ client = await Bun.connect({
+ tls: true,
+ hostname: address.address,
+ port: address.port,
+ socket: {
+ drain(socket) {
+ socket.write("Hello");
+ },
+ data(socket, data) {
+ is_done = true;
+ clearTimeout(timeout);
+ server.close();
+ socket.end();
+ expect(data.byteLength).toBe(5);
+ expect(data.toString("utf8")).toBe("Hello");
+ done();
+ },
+ handshake(socket) {
+ socket.write("Hello");
+ },
+ connectError: closeAndFail, // connection failed
+ },
+ }).catch(closeAndFail);
+ }),
+ );
+ });
+});