Volsatik

Untitled

Jun 9th, 2025
27
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.50 KB | None | 0 0
  1. local component = require("component")
  2. local computer = require("computer")
  3. local event = require("event")
  4. local internet = component.internet
  5.  
  6. -- Test configuration
  7. local TEST_SERVER_HOST = "20.20.20.100" -- localhost disabled in OC by default
  8. local TEST_SERVER_PORT = 8080
  9. local TIMEOUT = 30 -- seconds
  10.  
  11. -- Test results tracking
  12. local tests = {}
  13. local currentTest = nil
  14. local testResults = {passed = 0, failed = 0, total = 0}
  15.  
  16. -- Utility functions
  17. local function log(message)
  18. print("[" .. os.date("%H:%M:%S") .. "] " .. message)
  19. end
  20.  
  21. local function startTest(name)
  22. currentTest = {name = name, startTime = computer.uptime()}
  23. log("Starting test: " .. name)
  24. end
  25.  
  26. local function endTest(success, message)
  27. if not currentTest then return end
  28.  
  29. local duration = computer.uptime() - currentTest.startTime
  30. local result = success and "PASS" or "FAIL"
  31. local msg = message or ""
  32.  
  33. log(string.format("Test '%s' %s (%.2fs) %s", currentTest.name, result, duration, msg))
  34.  
  35. table.insert(tests, {
  36. name = currentTest.name,
  37. success = success,
  38. duration = duration,
  39. message = msg
  40. })
  41.  
  42. testResults.total = testResults.total + 1
  43. if success then
  44. testResults.passed = testResults.passed + 1
  45. else
  46. testResults.failed = testResults.failed + 1
  47. end
  48.  
  49. currentTest = nil
  50. end
  51.  
  52. local function waitForEvent(eventType, timeout, filter)
  53. local deadline = computer.uptime() + (timeout or TIMEOUT)
  54.  
  55. while computer.uptime() < deadline do
  56. local eventData = {computer.pullSignal(0.1)}
  57. if eventData[1] then
  58. if eventData[1] == eventType then
  59. if not filter or filter(eventData) then
  60. return eventData
  61. end
  62. elseif eventData[1] == "interrupted" then
  63. error("Test interrupted by user")
  64. end
  65. end
  66. end
  67.  
  68. return nil -- timeout
  69. end
  70.  
  71. -- WebSocket test functions
  72. local function testWebSocketBasicConnection()
  73. startTest("WebSocket Basic Connection")
  74.  
  75. if not internet.isWebSocketEnabled() then
  76. endTest(false, "WebSocket not enabled in settings")
  77. return
  78. end
  79.  
  80. local url = string.format("ws://%s:%d/echo", TEST_SERVER_HOST, TEST_SERVER_PORT)
  81. local ws = internet.websocket(url)
  82.  
  83. if not ws then
  84. endTest(false, "Failed to create WebSocket connection")
  85. return
  86. end
  87.  
  88. -- Wait for connection event
  89. local connectEvent = waitForEvent("websocket_connect", 10)
  90. if not connectEvent then
  91. endTest(false, "Connection timeout")
  92. ws.close()
  93. return
  94. end
  95.  
  96. if connectEvent[2] ~= ws then
  97. endTest(false, "Wrong connection handle in event")
  98. ws.close()
  99. return
  100. end
  101.  
  102. ws.close()
  103.  
  104. -- Wait for close event
  105. local closeEvent = waitForEvent("websocket_close", 5)
  106. if not closeEvent then
  107. endTest(false, "Close event timeout")
  108. return
  109. end
  110.  
  111. endTest(true, "Connection established and closed successfully")
  112. end
  113.  
  114. local function testWebSocketTextMessage()
  115. startTest("WebSocket Text Message")
  116.  
  117. local url = string.format("ws://%s:%d/echo", TEST_SERVER_HOST, TEST_SERVER_PORT)
  118. local ws = internet.websocket(url)
  119.  
  120. if not ws then
  121. endTest(false, "Failed to create WebSocket connection")
  122. return
  123. end
  124.  
  125. -- Wait for connection
  126. local connectEvent = waitForEvent("websocket_connect", 10)
  127. if not connectEvent then
  128. endTest(false, "Connection timeout")
  129. ws.close()
  130. return
  131. end
  132.  
  133. -- Send test message
  134. local testMessage = "Hello WebSocket!"
  135. ws.send(testMessage)
  136.  
  137. -- Wait for message event
  138. local messageEvent = waitForEvent("websocket_message", 10, function(evt)
  139. return evt[2] == ws and evt[3] == testMessage
  140. end)
  141.  
  142. if not messageEvent then
  143. endTest(false, "Message echo timeout or wrong content")
  144. ws.close()
  145. return
  146. end
  147.  
  148. ws.close()
  149. endTest(true, "Text message sent and received successfully")
  150. end
  151.  
  152. local function testWebSocketBinaryMessage()
  153. startTest("WebSocket Binary Message")
  154.  
  155. local url = string.format("ws://%s:%d/binary", TEST_SERVER_HOST, TEST_SERVER_PORT)
  156. local ws = internet.websocket(url)
  157.  
  158. if not ws then
  159. endTest(false, "Failed to create WebSocket connection")
  160. return
  161. end
  162.  
  163. -- Wait for connection
  164. local connectEvent = waitForEvent("websocket_connect", 10)
  165. if not connectEvent then
  166. endTest(false, "Connection timeout")
  167. ws.close()
  168. return
  169. end
  170.  
  171. -- Send binary data
  172. local binaryData = string.char(0x01, 0x02, 0x03, 0x04, 0x05, 0xFF, 0xFE)
  173. ws.send(binaryData, true) -- true for binary
  174.  
  175. -- Wait for binary message event
  176. local messageEvent = waitForEvent("websocket_message", 10, function(evt)
  177. return evt[2] == ws and evt[3] == binaryData and evt[4] == true
  178. end)
  179.  
  180. if not messageEvent then
  181. endTest(false, "Binary message echo timeout or wrong content")
  182. ws.close()
  183. return
  184. end
  185.  
  186. ws.close()
  187. endTest(true, "Binary message sent and received successfully")
  188. end
  189.  
  190. local function testWebSocketLargeMessage()
  191. startTest("WebSocket Large Message")
  192.  
  193. local url = string.format("ws://%s:%d/echo", TEST_SERVER_HOST, TEST_SERVER_PORT)
  194. local ws = internet.websocket(url)
  195.  
  196. if not ws then
  197. endTest(false, "Failed to create WebSocket connection")
  198. return
  199. end
  200.  
  201. -- Wait for connection
  202. local connectEvent = waitForEvent("websocket_connect", 10)
  203. if not connectEvent then
  204. endTest(false, "Connection timeout")
  205. ws.close()
  206. return
  207. end
  208.  
  209. -- Send large message (10KB)
  210. local largeMessage = string.rep("A", 10240)
  211. ws.send(largeMessage)
  212.  
  213. -- Wait for large message (may take longer)
  214. local messageEvent = waitForEvent("websocket_message", 20, function(evt)
  215. return evt[2] == ws and evt[3] == largeMessage
  216. end)
  217.  
  218. if not messageEvent then
  219. endTest(false, "Large message echo timeout or wrong content")
  220. ws.close()
  221. return
  222. end
  223.  
  224. ws.close()
  225. endTest(true, "Large message (10KB) sent and received successfully")
  226. end
  227.  
  228. local function testWebSocketFragmentation()
  229. startTest("WebSocket Fragmentation")
  230.  
  231. local url = string.format("ws://%s:%d/fragment", TEST_SERVER_HOST, TEST_SERVER_PORT)
  232. local ws = internet.websocket(url)
  233.  
  234. if not ws then
  235. endTest(false, "Failed to create WebSocket connection")
  236. return
  237. end
  238.  
  239. -- Wait for connection
  240. local connectEvent = waitForEvent("websocket_connect", 10)
  241. if not connectEvent then
  242. endTest(false, "Connection timeout")
  243. ws.close()
  244. return
  245. end
  246.  
  247. -- Send fragmentation test command
  248. ws.send("FRAGMENT_TEST")
  249.  
  250. -- Server should send fragmented message
  251. local fragments = {}
  252. local fragmentCount = 0
  253. local deadline = computer.uptime() + 15
  254.  
  255. while computer.uptime() < deadline do
  256. local messageEvent = waitForEvent("websocket_message", 2)
  257. if messageEvent and messageEvent[2] == ws then
  258. fragmentCount = fragmentCount + 1
  259. table.insert(fragments, messageEvent[3])
  260.  
  261. -- Expect 3 fragments
  262. if fragmentCount >= 3 then
  263. break
  264. end
  265. end
  266. end
  267.  
  268. if fragmentCount < 3 then
  269. endTest(false, string.format("Expected 3 fragments, got %d", fragmentCount))
  270. ws.close()
  271. return
  272. end
  273.  
  274. -- Verify fragment content
  275. local fullMessage = table.concat(fragments)
  276. local expectedMessage = "Fragment1Fragment2Fragment3"
  277.  
  278. if fullMessage ~= expectedMessage then
  279. endTest(false, "Fragmented message content mismatch")
  280. ws.close()
  281. return
  282. end
  283.  
  284. ws.close()
  285. endTest(true, "Fragmentation handled correctly")
  286. end
  287.  
  288. local function testWebSocketPingPong()
  289. startTest("WebSocket Ping/Pong")
  290.  
  291. local url = string.format("ws://%s:%d/ping", TEST_SERVER_HOST, TEST_SERVER_PORT)
  292. local ws = internet.websocket(url)
  293.  
  294. if not ws then
  295. endTest(false, "Failed to create WebSocket connection")
  296. return
  297. end
  298.  
  299. -- Wait for connection
  300. local connectEvent = waitForEvent("websocket_connect", 10)
  301. if not connectEvent then
  302. endTest(false, "Connection timeout")
  303. ws.close()
  304. return
  305. end
  306.  
  307. -- Send ping request
  308. ws.send("PING_TEST")
  309.  
  310. -- Wait for ping event
  311. local pingEvent = waitForEvent("websocket_ping", 10)
  312. if not pingEvent or pingEvent[2] ~= ws then
  313. endTest(false, "Ping event timeout")
  314. ws.close()
  315. return
  316. end
  317.  
  318. -- Pong should be sent automatically, wait for pong event
  319. local pongEvent = waitForEvent("websocket_pong", 5)
  320. if not pongEvent or pongEvent[2] ~= ws then
  321. endTest(false, "Pong event timeout")
  322. ws.close()
  323. return
  324. end
  325.  
  326. ws.close()
  327. endTest(true, "Ping/Pong handled correctly")
  328. end
  329.  
  330. local function testWebSocketCloseHandshake()
  331. startTest("WebSocket Close Handshake")
  332.  
  333. local url = string.format("ws://%s:%d/echo", TEST_SERVER_HOST, TEST_SERVER_PORT)
  334. local ws = internet.websocket(url)
  335.  
  336. if not ws then
  337. endTest(false, "Failed to create WebSocket connection")
  338. return
  339. end
  340.  
  341. -- Wait for connection
  342. local connectEvent = waitForEvent("websocket_connect", 10)
  343. if not connectEvent then
  344. endTest(false, "Connection timeout")
  345. ws.close()
  346. return
  347. end
  348.  
  349. -- Close with specific code and reason
  350. ws.close(1000, "Normal closure")
  351.  
  352. -- Wait for close event with proper code
  353. local closeEvent = waitForEvent("websocket_close", 10, function(evt)
  354. return evt[2] == ws and evt[3] == 1000 and evt[4] == "Normal closure"
  355. end)
  356.  
  357. if not closeEvent then
  358. endTest(false, "Close handshake failed or wrong parameters")
  359. return
  360. end
  361.  
  362. endTest(true, "Close handshake completed correctly")
  363. end
  364.  
  365. local function testWebSocketConnectionTimeout()
  366. startTest("WebSocket Connection Timeout")
  367.  
  368. -- Try to connect to non-existent server
  369. local url = "ws://192.168.255.255:9999/timeout"
  370. local ws = internet.websocket(url)
  371.  
  372. if not ws then
  373. endTest(true, "Connection correctly rejected immediately")
  374. return
  375. end
  376.  
  377. -- Wait for timeout or error
  378. local errorEvent = waitForEvent("websocket_error", 15)
  379. if not errorEvent or errorEvent[2] ~= ws then
  380. endTest(false, "Expected timeout error event")
  381. if ws then ws.close() end
  382. return
  383. end
  384.  
  385. endTest(true, "Connection timeout handled correctly")
  386. end
  387.  
  388. local function testWebSocketInvalidURL()
  389. startTest("WebSocket Invalid URL")
  390.  
  391. local invalidUrls = {
  392. "http://example.com", -- Wrong protocol
  393. "ftp://example.com", -- Wrong protocol
  394. "ws://", -- Incomplete URL
  395. "invalid-url", -- Malformed
  396. "" -- Empty
  397. }
  398.  
  399. local rejectedCount = 0
  400.  
  401. for _, url in ipairs(invalidUrls) do
  402. local success, ws = pcall(internet.websocket, url)
  403. if not success or not ws then
  404. rejectedCount = rejectedCount + 1
  405. else
  406. ws.close()
  407. end
  408. end
  409.  
  410. if rejectedCount == #invalidUrls then
  411. endTest(true, "All invalid URLs correctly rejected")
  412. else
  413. endTest(false, string.format("Only %d/%d invalid URLs rejected", rejectedCount, #invalidUrls))
  414. end
  415. end
  416.  
  417. local function testWebSocketSlowServer()
  418. startTest("WebSocket Slow Server Response")
  419.  
  420. local url = string.format("ws://%s:%d/slow", TEST_SERVER_HOST, TEST_SERVER_PORT)
  421. local ws = internet.websocket(url)
  422.  
  423. if not ws then
  424. endTest(false, "Failed to create WebSocket connection")
  425. return
  426. end
  427.  
  428. -- Wait for connection (server responds slowly)
  429. local connectEvent = waitForEvent("websocket_connect", 20)
  430. if not connectEvent then
  431. endTest(false, "Slow connection timeout")
  432. ws.close()
  433. return
  434. end
  435.  
  436. -- Send message to slow server
  437. ws.send("SLOW_MESSAGE")
  438.  
  439. -- Wait for slow response
  440. local messageEvent = waitForEvent("websocket_message", 25)
  441. if not messageEvent or messageEvent[2] ~= ws then
  442. endTest(false, "Slow message response timeout")
  443. ws.close()
  444. return
  445. end
  446.  
  447. ws.close()
  448. endTest(true, "Slow server handled without blocking game thread")
  449. end
  450.  
  451. local function testWebSocketMultipleConnections()
  452. startTest("WebSocket Multiple Connections")
  453.  
  454. local connections = {}
  455. local maxConnections = 5
  456.  
  457. -- Create multiple connections
  458. for i = 1, maxConnections do
  459. local url = string.format("ws://%s:%d/multi/%d", TEST_SERVER_HOST, TEST_SERVER_PORT, i)
  460. local ws = internet.websocket(url)
  461.  
  462. if ws then
  463. table.insert(connections, ws)
  464. end
  465. end
  466.  
  467. if #connections == 0 then
  468. endTest(false, "No connections could be established")
  469. return
  470. end
  471.  
  472. -- Wait for all connections
  473. local connectedCount = 0
  474. local deadline = computer.uptime() + 15
  475.  
  476. while computer.uptime() < deadline and connectedCount < #connections do
  477. local connectEvent = waitForEvent("websocket_connect", 1)
  478. if connectEvent then
  479. for _, ws in ipairs(connections) do
  480. if connectEvent[2] == ws then
  481. connectedCount = connectedCount + 1
  482. break
  483. end
  484. end
  485. end
  486. end
  487.  
  488. -- Test each connection
  489. local workingConnections = 0
  490. for i, ws in ipairs(connections) do
  491. ws.send("TEST_" .. i)
  492.  
  493. local messageEvent = waitForEvent("websocket_message", 5, function(evt)
  494. return evt[2] == ws
  495. end)
  496.  
  497. if messageEvent then
  498. workingConnections = workingConnections + 1
  499. end
  500. end
  501.  
  502. -- Close all connections
  503. for _, ws in ipairs(connections) do
  504. ws.close()
  505. end
  506.  
  507. if workingConnections >= math.min(3, #connections) then
  508. endTest(true, string.format("%d/%d connections working", workingConnections, #connections))
  509. else
  510. endTest(false, string.format("Only %d/%d connections working", workingConnections, #connections))
  511. end
  512. end
  513.  
  514. local function testWebSocketUTF8Handling()
  515. startTest("WebSocket UTF-8 Handling")
  516.  
  517. local url = string.format("ws://%s:%d/echo", TEST_SERVER_HOST, TEST_SERVER_PORT)
  518. local ws = internet.websocket(url)
  519.  
  520. if not ws then
  521. endTest(false, "Failed to create WebSocket connection")
  522. return
  523. end
  524.  
  525. -- Wait for connection
  526. local connectEvent = waitForEvent("websocket_connect", 10)
  527. if not connectEvent then
  528. endTest(false, "Connection timeout")
  529. ws.close()
  530. return
  531. end
  532.  
  533. -- Test various UTF-8 strings
  534. local utf8Tests = {
  535. "Hello, World!",
  536. "Привет, мир!",
  537. "こんにちは世界",
  538. "🌍🚀💻🎉",
  539. "Mixed: Hello мир 世界 🎉"
  540. }
  541.  
  542. local successCount = 0
  543.  
  544. for _, testString in ipairs(utf8Tests) do
  545. ws.send(testString)
  546.  
  547. local messageEvent = waitForEvent("websocket_message", 5, function(evt)
  548. return evt[2] == ws and evt[3] == testString
  549. end)
  550.  
  551. if messageEvent then
  552. successCount = successCount + 1
  553. end
  554. end
  555.  
  556. ws.close()
  557.  
  558. if successCount == #utf8Tests then
  559. endTest(true, "All UTF-8 strings handled correctly")
  560. else
  561. endTest(false, string.format("Only %d/%d UTF-8 strings handled", successCount, #utf8Tests))
  562. end
  563. end
  564.  
  565. -- Main test runner
  566. local function runAllTests()
  567. log("=== WebSocket Comprehensive Test Suite ===")
  568. log("Testing WebSocket RFC 6455 compliance and OpenComputers integration")
  569. log("")
  570.  
  571. -- Check if internet card is available
  572. if not internet then
  573. log("ERROR: Internet card not found!")
  574. return
  575. end
  576.  
  577. -- Run all tests
  578. local testFunctions = {
  579. testWebSocketBasicConnection,
  580. testWebSocketTextMessage,
  581. testWebSocketBinaryMessage,
  582. testWebSocketLargeMessage,
  583. testWebSocketFragmentation,
  584. testWebSocketPingPong,
  585. testWebSocketCloseHandshake,
  586. testWebSocketConnectionTimeout,
  587. testWebSocketInvalidURL,
  588. testWebSocketSlowServer,
  589. testWebSocketMultipleConnections,
  590. testWebSocketUTF8Handling
  591. }
  592.  
  593. local startTime = computer.uptime()
  594.  
  595. for _, testFunc in ipairs(testFunctions) do
  596. local success, error = pcall(testFunc)
  597. if not success then
  598. if currentTest then
  599. endTest(false, "Test crashed: " .. tostring(error))
  600. else
  601. log("ERROR: Test function crashed: " .. tostring(error))
  602. testResults.total = testResults.total + 1
  603. testResults.failed = testResults.failed + 1
  604. end
  605. end
  606.  
  607. -- Small delay between tests
  608. os.sleep(0.5)
  609. end
  610.  
  611. local totalTime = computer.uptime() - startTime
  612.  
  613. -- Print results
  614. log("")
  615. log("=== Test Results ===")
  616. log(string.format("Total tests: %d", testResults.total))
  617. log(string.format("Passed: %d", testResults.passed))
  618. log(string.format("Failed: %d", testResults.failed))
  619. log(string.format("Success rate: %.1f%%", (testResults.passed / testResults.total) * 100))
  620. log(string.format("Total time: %.2f seconds", totalTime))
  621. log("")
  622.  
  623. -- Detailed results
  624. for _, test in ipairs(tests) do
  625. local status = test.success and "PASS" or "FAIL"
  626. log(string.format(" %s: %s (%.2fs) %s", status, test.name, test.duration, test.message))
  627. end
  628.  
  629. log("")
  630. if testResults.failed == 0 then
  631. log("🎉 ALL TESTS PASSED! WebSocket implementation is working correctly.")
  632. else
  633. log("❌ Some tests failed. Check the results above.")
  634. end
  635.  
  636. return testResults.failed == 0
  637. end
  638.  
  639. -- Auto-start if run directly
  640. if not pcall(debug.getlocal, 4, 1) then
  641. runAllTests()
  642. end
  643.  
Advertisement
Add Comment
Please, Sign In to add comment