PageRenderTime 56ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/airvantage/luafwk/tests/socket.lua

https://github.com/CoRfr/legato-af
Lua | 663 lines | 597 code | 41 blank | 25 comment | 47 complexity | b548bc35897534003bec084b96638336 MD5 | raw file
Possible License(s): BSD-3-Clause, 0BSD, JSON, MIT
  1. -------------------------------------------------------------------------------
  2. -- Copyright (c) 2012 Sierra Wireless and others.
  3. -- All rights reserved. This program and the accompanying materials
  4. -- are made available under the terms of the Eclipse Public License v1.0
  5. -- which accompanies this distribution, and is available at
  6. -- http://www.eclipse.org/legal/epl-v10.html
  7. --
  8. -- Contributors:
  9. -- Diego Nehab - Original tests for LuaSocket 2.0.2
  10. -- Cuero Bugot for Sierra Wireless - Porting to unittest test harness
  11. -------------------------------------------------------------------------------
  12. local u = require 'unittest'
  13. local socket = require 'socket'
  14. local t=u.newtestsuite("socket")
  15. local enableDebugTests
  16. local control, data, err
  17. local host = "localhost"
  18. local port = "8383"
  19. local function fail(...)
  20. local s = string.format(...)
  21. u.fail(s)
  22. end
  23. local assert = u.assert
  24. local origtcpsend
  25. local origtcpreceive
  26. function t:setup()
  27. control, err = socket.connect(host, port)
  28. if not control then u.abort("Failed to setup TCP test server connection: ["..err.."]\r\nVerify that you launched the socket test server: \"lua luafwk/luasocket/sockettestsvr.lua\"") end
  29. control:setoption("tcp-nodelay", true)
  30. -- instrument the send/receive tcp client methods,
  31. -- in order to add time elapsed param (needed for the timeout tests)
  32. local mt=getmetatable(control).__index
  33. origtcpsend=mt.send
  34. origtcpreceive=mt.receive
  35. function mt.send(...)
  36. local t = os.time()
  37. local a, b, c = origtcpsend(...)
  38. return a, b, c, os.time()-t
  39. end
  40. function mt.receive(...)
  41. local t = os.time()
  42. local a, b, c = origtcpreceive(...)
  43. return a, b, c, os.time()-t
  44. end
  45. end
  46. function t:teardown()
  47. -- Restore original send/receive
  48. if control then
  49. local mt=getmetatable(control).__index
  50. mt.send=origtcpsend
  51. mt.receive=origtcpreceive
  52. end
  53. end
  54. local function test_methods(sock, methods)
  55. for _, v in pairs(methods) do
  56. u.assert_function(sock[v], 'function "'..v..'" missing')
  57. end
  58. end
  59. function t:test_tcp_methods()
  60. test_methods(socket.tcp(), {
  61. "accept",
  62. "bind",
  63. "close",
  64. "connect",
  65. "dirty",
  66. "getfd",
  67. "getpeername",
  68. "getsockname",
  69. "getstats",
  70. "setstats",
  71. "listen",
  72. "receive",
  73. "send",
  74. "setfd",
  75. "setoption",
  76. "setpeername",
  77. "setsockname",
  78. "settimeout",
  79. "shutdown",
  80. })
  81. end
  82. function t:test_udp_methods()
  83. test_methods(socket.udp(), {
  84. "close",
  85. "getpeername",
  86. "dirty",
  87. "getfd",
  88. "getpeername",
  89. "getsockname",
  90. "receive",
  91. "receivefrom",
  92. "send",
  93. "sendto",
  94. "setfd",
  95. "setoption",
  96. "setpeername",
  97. "setsockname",
  98. "settimeout"
  99. })
  100. end
  101. function remote(...)
  102. local s = string.format(...)
  103. s = string.gsub(s, "\n", ";")
  104. s = string.gsub(s, "%s+", " ")
  105. s = string.gsub(s, "^%s*", "")
  106. control:send(s .. "\n")
  107. control:receive()
  108. end
  109. local function reconnect()
  110. if data then data:close() end
  111. remote [[
  112. if data then data:close() data = nil end
  113. data = server:accept()
  114. data:setoption("tcp-nodelay", true)
  115. ]]
  116. data = assert(socket.connect(host, port))
  117. data:setoption("tcp-nodelay", true)
  118. end
  119. function t:test_readafterclose()
  120. local back, partial
  121. local str = 'little string'
  122. reconnect()
  123. --pass("trying repeated '*a' pattern")
  124. remote (string.format ([[
  125. data:send('%s')
  126. data:close()
  127. data = nil
  128. ]], str))
  129. back, err, partial = data:receive("*a")
  130. assert(back == str, "unexpected data read")
  131. back, err, partial = data:receive("*a")
  132. assert(back == nil and err == "closed", "should have returned 'closed'")
  133. reconnect()
  134. --pass("trying active close before '*a'")
  135. remote (string.format ([[
  136. data:close()
  137. data = nil
  138. ]]))
  139. data:close()
  140. back, err, partial = data:receive("*a")
  141. assert(back == nil and err == "closed", "should have returned 'closed'")
  142. reconnect()
  143. --pass("trying active close before '*l'")
  144. remote (string.format ([[
  145. data:close()
  146. data = nil
  147. ]]))
  148. data:close()
  149. back, err, partial = data:receive()
  150. assert(back == nil and err == "closed", "should have returned 'closed'")
  151. reconnect()
  152. --pass("trying active close before raw 1")
  153. remote (string.format ([[
  154. data:close()
  155. data = nil
  156. ]]))
  157. data:close()
  158. back, err, partial = data:receive(1)
  159. assert(back == nil and err == "closed", "should have returned 'closed'")
  160. reconnect()
  161. --pass("trying active close before raw 0")
  162. remote (string.format ([[
  163. data:close()
  164. data = nil
  165. ]]))
  166. data:close()
  167. back, err, partial = data:receive(0)
  168. assert(back == nil and err == "closed", "should have returned 'closed'")
  169. end
  170. function t:test_selectbugs()
  171. local r, s, e = socket.select(nil, nil, 0.1)
  172. assert(type(r) == "table" and type(s) == "table" and
  173. (e == "timeout" or e == "error"))
  174. --pass("both nil: ok")
  175. local udp = socket.udp()
  176. udp:close()
  177. r, s, e = socket.select({ udp }, { udp }, 0.1)
  178. assert(type(r) == "table" and type(s) == "table" and
  179. (e == "timeout" or e == "error"))
  180. --pass("closed sockets: ok")
  181. e = pcall(socket.select, "wrong", 1, 0.1)
  182. assert(e == false)
  183. e = pcall(socket.select, {}, 1, 0.1)
  184. assert(e == false)
  185. --pass("invalid input: ok")
  186. end
  187. function t:test_connect_timeout()
  188. local t = socket.gettime()
  189. local c, e = socket.tcp()
  190. assert(c, e)
  191. c:settimeout(0.1)
  192. local t = socket.gettime()
  193. local r, e = c:connect("10.0.0.1", 81)
  194. assert(not r, "should not connect")
  195. assert(socket.gettime() - t < 2, "took too long to give up.")
  196. c:close()
  197. end
  198. function t:test_empty_connect()
  199. reconnect()
  200. if data then data:close() data = nil end
  201. remote [[
  202. if data then data:close() data = nil end
  203. data = server:accept()
  204. ]]
  205. data, err = socket.connect("", port)
  206. if not data then
  207. data = socket.connect(host, port)
  208. else
  209. fail("gethostbyname returns localhost on empty string...")
  210. end
  211. end
  212. function t:test_connect_errors()
  213. local c, e = socket.connect("localhost", 1);
  214. assert(not c and e)
  215. local c, e = socket.connect("host.is.invalid", 1);
  216. assert(not c and e, e)
  217. end
  218. function t:test_rebind()
  219. local r
  220. local c = socket.bind("localhost", 0)
  221. local i, p = c:getsockname()
  222. local s, e = socket.tcp()
  223. assert(s, e)
  224. s:setoption("reuseaddr", false)
  225. r, e = s:bind("localhost", p)
  226. assert(not r, "managed to rebind!")
  227. assert(e)
  228. end
  229. local function isclosed(c)
  230. return c:getfd() == -1 or c:getfd() == (2^32-1)
  231. end
  232. function t:test_active_close()
  233. reconnect()
  234. if isclosed(data) then fail("should not be closed") end
  235. data:close()
  236. if not isclosed(data) then fail("should be closed") end
  237. data = nil
  238. local udp = socket.udp()
  239. if isclosed(udp) then fail("should not be closed") end
  240. udp:close()
  241. if not isclosed(udp) then fail("should be closed") end
  242. end
  243. function t:test_closed()
  244. local back, partial, err, total
  245. local str = 'little string'
  246. reconnect()
  247. --pass("trying read detection")
  248. remote (string.format ([[
  249. data:send('%s')
  250. data:close()
  251. data = nil
  252. ]], str))
  253. -- try to get a line
  254. back, err, partial = data:receive()
  255. if not err then fail("should have gotten 'closed'.")
  256. elseif err ~= "closed" then fail("got '"..err.."' instead of 'closed'.")
  257. elseif str ~= partial then fail("didn't receive partial result.")
  258. end
  259. reconnect()
  260. --pass("trying write detection")
  261. remote [[
  262. data:close()
  263. data = nil
  264. ]]
  265. total, err, partial = data:send(string.rep("ugauga", 100000))
  266. if not err then
  267. fail("failed: output buffer is at least %d bytes long!", total)
  268. elseif err ~= "closed" then
  269. fail("got '"..err.."' instead of 'closed'.")
  270. end
  271. end
  272. function t:test_accept_timeout()
  273. local s, e = socket.bind("*", 0, 0)
  274. assert(s, e)
  275. local t = socket.gettime()
  276. s:settimeout(1)
  277. local c, e = s:accept()
  278. assert(not c, "should not accept")
  279. assert(e == "timeout", string.format("wrong error message (%s)", e))
  280. t = socket.gettime() - t
  281. assert(t < 2, string.format("took to long to give up (%gs)", t))
  282. s:close()
  283. end
  284. function t:test_accept_errors()
  285. local d, e = socket.bind("*", 0)
  286. assert(d, e);
  287. local c, e = socket.tcp();
  288. assert(c, e);
  289. d:setfd(c:getfd())
  290. d:settimeout(2)
  291. local r, e = d:accept()
  292. assert(not r and e)
  293. local c, e = socket.udp()
  294. assert(c, e);
  295. d:setfd(c:getfd())
  296. local r, e = d:accept()
  297. assert(not r and e)
  298. end
  299. function t:test_getstats()
  300. reconnect()
  301. local t = 0
  302. for i = 1, 25 do
  303. local c = math.random(1, 100)
  304. remote (string.format ([[
  305. str = data:receive(%d)
  306. data:send(str)
  307. ]], c))
  308. data:send(string.rep("a", c))
  309. data:receive(c)
  310. t = t + c
  311. local r, s, a = data:getstats()
  312. assert(r == t, "received count failed" .. tostring(r)
  313. .. "/" .. tostring(t))
  314. assert(s == t, "sent count failed" .. tostring(s)
  315. .. "/" .. tostring(t))
  316. end
  317. end
  318. local function test_asciiline(len)
  319. reconnect()
  320. local str, str10, back
  321. str = string.rep("x", math.mod(len, 10))
  322. str10 = string.rep("aZb.c#dAe?", math.floor(len/10))
  323. str = str .. str10
  324. remote "str = data:receive()"
  325. assert(data:send(str.."\n"))
  326. remote "data:send(str ..'\\n')"
  327. back = assert(data:receive())
  328. if back == str then --pass("lines match")
  329. else fail("lines don't match") end
  330. end
  331. function t:test_asciiline()
  332. test_asciiline(1)
  333. test_asciiline(17)
  334. test_asciiline(200)
  335. test_asciiline(4091)
  336. test_asciiline(80199)
  337. test_asciiline(8000000)
  338. test_asciiline(80199)
  339. test_asciiline(4091)
  340. test_asciiline(200)
  341. test_asciiline(17)
  342. test_asciiline(1)
  343. end
  344. local function test_mixed(len)
  345. reconnect()
  346. local inter = math.ceil(len/4)
  347. local p1 = "unix " .. string.rep("x", inter) .. "line\n"
  348. local p2 = "dos " .. string.rep("y", inter) .. "line\r\n"
  349. local p3 = "raw " .. string.rep("z", inter) .. "bytes"
  350. local p4 = "end" .. string.rep("w", inter) .. "bytes"
  351. local bp1, bp2, bp3, bp4
  352. remote (string.format("str = data:receive(%d)",
  353. string.len(p1)+string.len(p2)+string.len(p3)+string.len(p4)))
  354. assert(data:send(p1..p2..p3..p4))
  355. remote "data:send(str); data:close()"
  356. bp1 = assert(data:receive())
  357. bp2 = assert(data:receive())
  358. bp3 = assert(data:receive(string.len(p3)))
  359. bp4 = assert(data:receive("*a"))
  360. if bp1.."\n" == p1 and bp2.."\r\n" == p2 and bp3 == p3 and bp4 == p4 then
  361. --pass("patterns match")
  362. else fail("patterns don't match") end
  363. end
  364. function t:test_mixed()
  365. test_mixed(1)
  366. test_mixed(17)
  367. test_mixed(200)
  368. test_mixed(4091)
  369. test_mixed(801990)
  370. test_mixed(4091)
  371. test_mixed(200)
  372. test_mixed(17)
  373. test_mixed(1)
  374. end
  375. local function test_rawline(len)
  376. reconnect()
  377. local str, str10, back, err
  378. str = string.rep(string.char(47), math.mod(len, 10))
  379. str10 = string.rep(string.char(120,21,77,4,5,0,7,36,44,100),
  380. math.floor(len/10))
  381. str = str .. str10
  382. remote "str = data:receive()"
  383. assert(data:send(str.."\n"))
  384. remote "data:send(str..'\\n')"
  385. back = assert(data:receive())
  386. if err then fail(err) end
  387. assert(back == str, "lines don't match")
  388. end
  389. function t:test_rawline()
  390. test_rawline(1)
  391. test_rawline(17)
  392. test_rawline(200)
  393. test_rawline(4091)
  394. test_rawline(80199)
  395. test_rawline(8000000)
  396. test_rawline(80199)
  397. test_rawline(4091)
  398. test_rawline(200)
  399. test_rawline(17)
  400. test_rawline(1)
  401. end
  402. local function test_raw(len)
  403. reconnect()
  404. local half = math.floor(len/2)
  405. local s1, s2, back, err
  406. s1 = string.rep("x", half)
  407. s2 = string.rep("y", len-half)
  408. remote (string.format("str = data:receive(%d)", len))
  409. assert(data:send(s1))
  410. assert(data:send(s2))
  411. remote "data:send(str)"
  412. back = assert(data:receive(len))
  413. assert( back == s1..s2, "blocks don't match")
  414. end
  415. function t:test_raw()
  416. test_raw(1)
  417. test_raw(17)
  418. test_raw(200)
  419. test_raw(4091)
  420. test_raw(80199)
  421. test_raw(8000000)
  422. test_raw(80199)
  423. test_raw(4091)
  424. test_raw(200)
  425. test_raw(17)
  426. test_raw(1)
  427. end
  428. local function test_nonblocking(size)
  429. reconnect()
  430. remote(string.format([[
  431. data:send(string.rep("a", %d))
  432. socket.sleep(0.5)
  433. data:send(string.rep("b", %d) .. "\n")
  434. ]], size, size))
  435. local err = "timeout"
  436. local part = ""
  437. local str, ret
  438. data:settimeout(0)
  439. while 1 do
  440. str, err, part = data:receive("*l", part)
  441. if err ~= "timeout" then break end
  442. end
  443. assert(str == (string.rep("a", size) .. string.rep("b", size)))
  444. reconnect()
  445. remote(string.format([[
  446. str = data:receive(%d)
  447. socket.sleep(0.5)
  448. str = data:receive(2*%d, str)
  449. data:send(str)
  450. ]], size, size))
  451. data:settimeout(0)
  452. local start = 0
  453. while 1 do
  454. ret, err, start = data:send(str, start+1)
  455. if err ~= "timeout" then break end
  456. end
  457. data:send("\n")
  458. data:settimeout(-1)
  459. local back = data:receive(2*size)
  460. assert(back == str, "'" .. back .. "' vs '" .. str .. "'")
  461. end
  462. function t:test_nonblocking()
  463. test_nonblocking(1)
  464. test_nonblocking(17)
  465. test_nonblocking(200)
  466. test_nonblocking(4091)
  467. test_nonblocking(80199)
  468. test_nonblocking(800000)
  469. test_nonblocking(80199)
  470. test_nonblocking(4091)
  471. test_nonblocking(200)
  472. test_nonblocking(17)
  473. test_nonblocking(1)
  474. end
  475. local function check_timeout(tm, sl, elapsed, err, opp, mode, alldone)
  476. if tm < sl then
  477. if opp == "send" then
  478. assert(not err or err == "timeout", err)
  479. else
  480. assert(err == "timeout")
  481. end
  482. else
  483. if mode == "total" then
  484. if elapsed > tm then
  485. assert(err == "timeout", err)
  486. elseif elapsed < tm then
  487. if err then fail(err) end
  488. else
  489. if alldone then
  490. if err then fail("unexpected error '%s'", err) end
  491. else
  492. assert(err == "timeout", err)
  493. end
  494. end
  495. else
  496. assert(not err, err)
  497. end
  498. end
  499. end
  500. local function test_totaltimeoutsend(len, tm, sl)
  501. reconnect()
  502. local str, err, total, elapsed, partial
  503. remote (string.format ([[
  504. data:settimeout(%d)
  505. str = data:receive(%d)
  506. print('server: sleeping for %ds')
  507. socket.sleep(%d)
  508. print('server: woke up')
  509. str = data:receive(%d)
  510. ]], 2*tm, len, sl, sl, len))
  511. data:settimeout(tm, "total")
  512. str = string.rep("a", 2*len)
  513. total, err, partial, elapsed = data:send(str)
  514. check_timeout(tm, sl, elapsed, err, "send", "total",
  515. total == 2*len)
  516. end
  517. function t:test_totaltimeoutsend()
  518. test_totaltimeoutsend(800091, 1, 3)
  519. test_totaltimeoutsend(800091, 2, 3)
  520. test_totaltimeoutsend(800091, 5, 2)
  521. test_totaltimeoutsend(800091, 3, 1)
  522. end
  523. local function test_totaltimeoutreceive(len, tm, sl)
  524. reconnect()
  525. local str, err, partial, elapsed
  526. remote (string.format ([[
  527. data:settimeout(%d)
  528. str = string.rep('a', %d)
  529. data:send(str)
  530. print('server: sleeping for %ds')
  531. socket.sleep(%d)
  532. print('server: woke up')
  533. data:send(str)
  534. ]], 2*tm, len, sl, sl))
  535. data:settimeout(tm, "total")
  536. local t = socket.gettime()
  537. str, err, partial, elapsed = data:receive(2*len)
  538. check_timeout(tm, sl, elapsed, err, "receive", "total",
  539. string.len(str or partial or "") == 2*len)
  540. end
  541. function t:test_totaltimeoutreceive()
  542. test_totaltimeoutreceive(800091, 1, 3)
  543. test_totaltimeoutreceive(800091, 2, 3)
  544. test_totaltimeoutreceive(800091, 3, 2)
  545. test_totaltimeoutreceive(800091, 3, 1)
  546. end
  547. local function test_blockingtimeoutsend(len, tm, sl)
  548. reconnect()
  549. local str, err, total, elapsed, partial
  550. remote (string.format ([[
  551. data:settimeout(%d)
  552. str = data:receive(%d)
  553. print('server: sleeping for %ds')
  554. socket.sleep(%d)
  555. print('server: woke up')
  556. str = data:receive(%d)
  557. ]], 2*tm, len, sl, sl, len))
  558. data:settimeout(tm)
  559. str = string.rep("a", 2*len)
  560. total, err, partial, elapsed = data:send(str)
  561. check_timeout(tm, sl, elapsed, err, "send", "blocking",
  562. total == 2*len)
  563. end
  564. function t:test_blockingtimeoutsend()
  565. test_blockingtimeoutsend(128, 1, 3)
  566. test_blockingtimeoutsend(128, 2, 3)
  567. test_blockingtimeoutsend(128, 3, 2)
  568. test_blockingtimeoutsend(128, 3, 1)
  569. end
  570. local function test_blockingtimeoutreceive(len, tm, sl)
  571. reconnect()
  572. local str, err, partial, elapsed
  573. remote (string.format ([[
  574. data:settimeout(%d)
  575. str = string.rep('a', %d)
  576. data:send(str)
  577. print('server: sleeping for %ds')
  578. socket.sleep(%d)
  579. print('server: woke up')
  580. data:send(str)
  581. ]], 2*tm, len, sl, sl))
  582. data:settimeout(tm)
  583. str, err, partial, elapsed = data:receive(2*len)
  584. check_timeout(tm, sl, elapsed, err, "receive", "blocking",
  585. string.len(str or partial) == 2*len)
  586. end
  587. function t:test_blockingtimeoutreceive()
  588. test_blockingtimeoutreceive(128, 1, 3)
  589. test_blockingtimeoutreceive(128, 2, 3)
  590. test_blockingtimeoutreceive(128, 3, 2)
  591. test_blockingtimeoutreceive(128, 3, 1)
  592. end