ltn12test.lua 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. local ltn12 = require("ltn12")
  2. dofile("testsupport.lua")
  3. local function format(chunk)
  4. if chunk then
  5. if chunk == "" then return "''"
  6. else return string.len(chunk) end
  7. else return "nil" end
  8. end
  9. local function show(name, input, output)
  10. local sin = format(input)
  11. local sout = format(output)
  12. io.write(name, ": ", sin, " -> ", sout, "\n")
  13. end
  14. local function chunked(length)
  15. local tmp
  16. return function(chunk)
  17. local ret
  18. if chunk and chunk ~= "" then
  19. tmp = chunk
  20. end
  21. ret = string.sub(tmp, 1, length)
  22. tmp = string.sub(tmp, length+1)
  23. if not chunk and ret == "" then ret = nil end
  24. return ret
  25. end
  26. end
  27. local function named(f, name)
  28. return function(chunk)
  29. local ret = f(chunk)
  30. show(name, chunk, ret)
  31. return ret
  32. end
  33. end
  34. --------------------------------
  35. local function split(size)
  36. local buffer = ""
  37. local last_out = ""
  38. local last_in = ""
  39. local function output(chunk)
  40. local part = string.sub(buffer, 1, size)
  41. buffer = string.sub(buffer, size+1)
  42. last_out = (part ~= "" or chunk) and part
  43. last_in = chunk
  44. return last_out
  45. end
  46. return function(chunk, done)
  47. if done then
  48. return not last_in and not last_out
  49. end
  50. -- check if argument is consistent with state
  51. if not chunk then
  52. if last_in and last_in ~= "" and last_out ~= "" then
  53. error("nil chunk following data chunk", 2)
  54. end
  55. if not last_out then error("extra nil chunk", 2) end
  56. return output(chunk)
  57. elseif chunk == "" then
  58. if last_out == "" then error('extra "" chunk', 2) end
  59. if not last_out then error('"" chunk following nil return', 2) end
  60. if not last_in then error('"" chunk following nil chunk', 2) end
  61. return output(chunk)
  62. else
  63. if not last_in then error("data chunk following nil chunk", 2) end
  64. if last_in ~= "" and last_out ~= "" then
  65. error("data chunk following data chunk", 2)
  66. end
  67. buffer = chunk
  68. return output(chunk)
  69. end
  70. end
  71. end
  72. --------------------------------
  73. local function format(chunk)
  74. if chunk then
  75. if chunk == "" then return "''"
  76. else return string.len(chunk) end
  77. else return "nil" end
  78. end
  79. --------------------------------
  80. local function merge(size)
  81. local buffer = ""
  82. local last_out = ""
  83. local last_in = ""
  84. local function output(chunk)
  85. local part
  86. if string.len(buffer) >= size or not chunk then
  87. part = buffer
  88. buffer = ""
  89. else
  90. part = ""
  91. end
  92. last_out = (part ~= "" or chunk) and part
  93. last_in = chunk
  94. return last_out
  95. end
  96. return function(chunk, done)
  97. if done then
  98. return not last_in and not last_out
  99. end
  100. -- check if argument is consistent with state
  101. if not chunk then
  102. if last_in and last_in ~= "" and last_out ~= "" then
  103. error("nil chunk following data chunk", 2)
  104. end
  105. if not last_out then error("extra nil chunk", 2) end
  106. return output(chunk)
  107. elseif chunk == "" then
  108. if last_out == "" then error('extra "" chunk', 2) end
  109. if not last_out then error('"" chunk following nil return', 2) end
  110. if not last_in then error('"" chunk following nil chunk', 2) end
  111. return output(chunk)
  112. else
  113. if not last_in then error("data chunk following nil chunk", 2) end
  114. if last_in ~= "" and last_out ~= "" then
  115. error("data chunk following data chunk", 2)
  116. end
  117. buffer = buffer .. chunk
  118. return output(chunk)
  119. end
  120. end
  121. end
  122. --------------------------------
  123. io.write("testing sink.table: ")
  124. local sink, t = ltn12.sink.table()
  125. local s, c = "", ""
  126. for i = 0, 10 do
  127. c = string.rep(string.char(i), i)
  128. s = s .. c
  129. assert(sink(c), "returned error")
  130. end
  131. assert(sink(nil), "returned error")
  132. assert(table.concat(t) == s, "mismatch")
  133. print("ok")
  134. --------------------------------
  135. io.write("testing sink.chain (with split): ")
  136. sink, t = ltn12.sink.table()
  137. local filter = split(3)
  138. sink = ltn12.sink.chain(filter, sink)
  139. s = "123456789012345678901234567890"
  140. assert(sink(s), "returned error")
  141. assert(sink(s), "returned error")
  142. assert(sink(nil), "returned error")
  143. assert(table.concat(t) == s .. s, "mismatch")
  144. assert(filter(nil, 1), "filter not empty")
  145. print("ok")
  146. --------------------------------
  147. io.write("testing sink.chain (with merge): ")
  148. sink, t = ltn12.sink.table()
  149. filter = merge(10)
  150. sink = ltn12.sink.chain(filter, sink)
  151. s = string.rep("123", 30)
  152. s = s .. string.rep("4321", 30)
  153. for i = 1, 30 do
  154. assert(sink("123"), "returned error")
  155. end
  156. for i = 1, 30 do
  157. assert(sink("4321"), "returned error")
  158. end
  159. assert(sink(nil), "returned error")
  160. assert(filter(nil, 1), "filter not empty")
  161. assert(table.concat(t) == s, "mismatch")
  162. print("ok")
  163. --------------------------------
  164. io.write("testing source.string and pump.all: ")
  165. local source = ltn12.source.string(s)
  166. sink, t = ltn12.sink.table()
  167. assert(ltn12.pump.all(source, sink), "returned error")
  168. assert(table.concat(t) == s, "mismatch")
  169. print("ok")
  170. --------------------------------
  171. io.write("testing source.chain (with split): ")
  172. source = ltn12.source.string(s)
  173. filter = split(5)
  174. source = ltn12.source.chain(source, filter)
  175. sink, t = ltn12.sink.table()
  176. assert(ltn12.pump.all(source, sink), "returned error")
  177. assert(table.concat(t) == s, "mismatch")
  178. assert(filter(nil, 1), "filter not empty")
  179. print("ok")
  180. --------------------------------
  181. io.write("testing source.chain (with several filters): ")
  182. local function double(x) -- filter turning "ABC" into "AABBCC"
  183. if not x then return end
  184. local b={}
  185. for k in x:gmatch'.' do table.insert(b, k..k) end
  186. return table.concat(b)
  187. end
  188. source = ltn12.source.string(s)
  189. source = ltn12.source.chain(source, double, double, double)
  190. sink, t = ltn12.sink.table()
  191. assert(ltn12.pump.all(source, sink), "returned error")
  192. assert(table.concat(t) == double(double(double(s))), "mismatch")
  193. print("ok")
  194. --------------------------------
  195. io.write("testing source.chain (with split) and sink.chain (with merge): ")
  196. source = ltn12.source.string(s)
  197. filter = split(5)
  198. source = ltn12.source.chain(source, filter)
  199. local filter2 = merge(13)
  200. sink, t = ltn12.sink.table()
  201. sink = ltn12.sink.chain(filter2, sink)
  202. assert(ltn12.pump.all(source, sink), "returned error")
  203. assert(table.concat(t) == s, "mismatch")
  204. assert(filter(nil, 1), "filter not empty")
  205. assert(filter2(nil, 1), "filter2 not empty")
  206. print("ok")
  207. --------------------------------
  208. io.write("testing sink.chain (with several filters): ")
  209. source = ltn12.source.string(s)
  210. sink, t = ltn12.sink.table()
  211. sink = ltn12.sink.chain(double, double, double, sink)
  212. assert(ltn12.pump.all(source, sink), "returned error")
  213. assert(table.concat(t) == double(double(double(s))), "mismatch")
  214. print("ok")
  215. --------------------------------
  216. io.write("testing filter.chain (and sink.chain, with split, merge): ")
  217. source = ltn12.source.string(s)
  218. filter = split(5)
  219. filter2 = merge(13)
  220. local chain = ltn12.filter.chain(filter, filter2)
  221. sink, t = ltn12.sink.table()
  222. sink = ltn12.sink.chain(chain, sink)
  223. assert(ltn12.pump.all(source, sink), "returned error")
  224. assert(table.concat(t) == s, "mismatch")
  225. assert(filter(nil, 1), "filter not empty")
  226. assert(filter2(nil, 1), "filter2 not empty")
  227. print("ok")
  228. --------------------------------
  229. io.write("testing filter.chain (and sink.chain, a bunch): ")
  230. source = ltn12.source.string(s)
  231. filter = split(5)
  232. filter2 = merge(13)
  233. local filter3 = split(7)
  234. local filter4 = merge(11)
  235. local filter5 = split(10)
  236. chain = ltn12.filter.chain(filter, filter2, filter3, filter4, filter5)
  237. sink, t = ltn12.sink.table()
  238. sink = ltn12.sink.chain(chain, sink)
  239. assert(ltn12.pump.all(source, sink))
  240. assert(table.concat(t) == s, "mismatch")
  241. assert(filter(nil, 1), "filter not empty")
  242. assert(filter2(nil, 1), "filter2 not empty")
  243. assert(filter3(nil, 1), "filter3 not empty")
  244. assert(filter4(nil, 1), "filter4 not empty")
  245. assert(filter5(nil, 1), "filter5 not empty")
  246. print("ok")
  247. --------------------------------
  248. io.write("testing filter.chain (and source.chain, with split, merge): ")
  249. source = ltn12.source.string(s)
  250. filter = split(5)
  251. filter2 = merge(13)
  252. local chain = ltn12.filter.chain(filter, filter2)
  253. sink, t = ltn12.sink.table()
  254. source = ltn12.source.chain(source, chain)
  255. assert(ltn12.pump.all(source, sink), "returned error")
  256. assert(table.concat(t) == s, "mismatch")
  257. assert(filter(nil, 1), "filter not empty")
  258. assert(filter2(nil, 1), "filter2 not empty")
  259. print("ok")
  260. --------------------------------
  261. io.write("testing filter.chain (and source.chain, a bunch): ")
  262. source = ltn12.source.string(s)
  263. filter = split(5)
  264. filter2 = merge(13)
  265. local filter3 = split(7)
  266. local filter4 = merge(11)
  267. local filter5 = split(10)
  268. chain = ltn12.filter.chain(filter, filter2, filter3, filter4, filter5)
  269. sink, t = ltn12.sink.table()
  270. source = ltn12.source.chain(source, chain)
  271. assert(ltn12.pump.all(source, sink))
  272. assert(table.concat(t) == s, "mismatch")
  273. assert(filter(nil, 1), "filter not empty")
  274. assert(filter2(nil, 1), "filter2 not empty")
  275. assert(filter3(nil, 1), "filter3 not empty")
  276. assert(filter4(nil, 1), "filter4 not empty")
  277. assert(filter5(nil, 1), "filter5 not empty")
  278. print("ok")