test.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. var tape = require('tape')
  2. var through = require('through2')
  3. var concat = require('concat-stream')
  4. var net = require('net')
  5. var duplexify = require('./')
  6. var HELLO_WORLD = (Buffer.from && Buffer.from !== Uint8Array.from)
  7. ? Buffer.from('hello world')
  8. : new Buffer('hello world')
  9. tape('passthrough', function(t) {
  10. t.plan(2)
  11. var pt = through()
  12. var dup = duplexify(pt, pt)
  13. dup.end('hello world')
  14. dup.on('finish', function() {
  15. t.ok(true, 'should finish')
  16. })
  17. dup.pipe(concat(function(data) {
  18. t.same(data.toString(), 'hello world', 'same in as out')
  19. }))
  20. })
  21. tape('passthrough + double end', function(t) {
  22. t.plan(2)
  23. var pt = through()
  24. var dup = duplexify(pt, pt)
  25. dup.end('hello world')
  26. dup.end()
  27. dup.on('finish', function() {
  28. t.ok(true, 'should finish')
  29. })
  30. dup.pipe(concat(function(data) {
  31. t.same(data.toString(), 'hello world', 'same in as out')
  32. }))
  33. })
  34. tape('async passthrough + end', function(t) {
  35. t.plan(2)
  36. var pt = through.obj({highWaterMark:1}, function(data, enc, cb) {
  37. setTimeout(function() {
  38. cb(null, data)
  39. }, 100)
  40. })
  41. var dup = duplexify(pt, pt)
  42. dup.write('hello ')
  43. dup.write('world')
  44. dup.end()
  45. dup.on('finish', function() {
  46. t.ok(true, 'should finish')
  47. })
  48. dup.pipe(concat(function(data) {
  49. t.same(data.toString(), 'hello world', 'same in as out')
  50. }))
  51. })
  52. tape('duplex', function(t) {
  53. var readExpected = ['read-a', 'read-b', 'read-c']
  54. var writeExpected = ['write-a', 'write-b', 'write-c']
  55. t.plan(readExpected.length+writeExpected.length+2)
  56. var readable = through.obj()
  57. var writable = through.obj(function(data, enc, cb) {
  58. t.same(data, writeExpected.shift(), 'onwrite should match')
  59. cb()
  60. })
  61. var dup = duplexify.obj(writable, readable)
  62. readExpected.slice().forEach(function(data) {
  63. readable.write(data)
  64. })
  65. readable.end()
  66. writeExpected.slice().forEach(function(data) {
  67. dup.write(data)
  68. })
  69. dup.end()
  70. dup.on('data', function(data) {
  71. t.same(data, readExpected.shift(), 'ondata should match')
  72. })
  73. dup.on('end', function() {
  74. t.ok(true, 'should end')
  75. })
  76. dup.on('finish', function() {
  77. t.ok(true, 'should finish')
  78. })
  79. })
  80. tape('async', function(t) {
  81. var dup = duplexify()
  82. var pt = through()
  83. dup.pipe(concat(function(data) {
  84. t.same(data.toString(), 'i was async', 'same in as out')
  85. t.end()
  86. }))
  87. dup.write('i')
  88. dup.write(' was ')
  89. dup.end('async')
  90. setTimeout(function() {
  91. dup.setWritable(pt)
  92. setTimeout(function() {
  93. dup.setReadable(pt)
  94. }, 50)
  95. }, 50)
  96. })
  97. tape('destroy', function(t) {
  98. t.plan(2)
  99. var write = through()
  100. var read = through()
  101. var dup = duplexify(write, read)
  102. write.destroy = function() {
  103. t.ok(true, 'write destroyed')
  104. }
  105. dup.on('close', function() {
  106. t.ok(true, 'close emitted')
  107. })
  108. dup.destroy()
  109. dup.destroy() // should only work once
  110. })
  111. tape('destroy both', function(t) {
  112. t.plan(3)
  113. var write = through()
  114. var read = through()
  115. var dup = duplexify(write, read)
  116. write.destroy = function() {
  117. t.ok(true, 'write destroyed')
  118. }
  119. read.destroy = function() {
  120. t.ok(true, 'read destroyed')
  121. }
  122. dup.on('close', function() {
  123. t.ok(true, 'close emitted')
  124. })
  125. dup.destroy()
  126. dup.destroy() // should only work once
  127. })
  128. tape('bubble read errors', function(t) {
  129. t.plan(2)
  130. var write = through()
  131. var read = through()
  132. var dup = duplexify(write, read)
  133. dup.on('error', function(err) {
  134. t.same(err.message, 'read-error', 'received read error')
  135. })
  136. dup.on('close', function() {
  137. t.ok(true, 'close emitted')
  138. })
  139. read.emit('error', new Error('read-error'))
  140. write.emit('error', new Error('write-error')) // only emit first error
  141. })
  142. tape('bubble write errors', function(t) {
  143. t.plan(2)
  144. var write = through()
  145. var read = through()
  146. var dup = duplexify(write, read)
  147. dup.on('error', function(err) {
  148. t.same(err.message, 'write-error', 'received write error')
  149. })
  150. dup.on('close', function() {
  151. t.ok(true, 'close emitted')
  152. })
  153. write.emit('error', new Error('write-error'))
  154. read.emit('error', new Error('read-error')) // only emit first error
  155. })
  156. tape('reset writable / readable', function(t) {
  157. t.plan(3)
  158. var toUpperCase = function(data, enc, cb) {
  159. cb(null, data.toString().toUpperCase())
  160. }
  161. var passthrough = through()
  162. var upper = through(toUpperCase)
  163. var dup = duplexify(passthrough, passthrough)
  164. dup.once('data', function(data) {
  165. t.same(data.toString(), 'hello')
  166. dup.setWritable(upper)
  167. dup.setReadable(upper)
  168. dup.once('data', function(data) {
  169. t.same(data.toString(), 'HELLO')
  170. dup.once('data', function(data) {
  171. t.same(data.toString(), 'HI')
  172. t.end()
  173. })
  174. })
  175. dup.write('hello')
  176. dup.write('hi')
  177. })
  178. dup.write('hello')
  179. })
  180. tape('cork', function(t) {
  181. var passthrough = through()
  182. var dup = duplexify(passthrough, passthrough)
  183. var ok = false
  184. dup.on('prefinish', function() {
  185. dup.cork()
  186. setTimeout(function() {
  187. ok = true
  188. dup.uncork()
  189. }, 100)
  190. })
  191. dup.on('finish', function() {
  192. t.ok(ok)
  193. t.end()
  194. })
  195. dup.end()
  196. })
  197. tape('prefinish not twice', function(t) {
  198. var passthrough = through()
  199. var dup = duplexify(passthrough, passthrough)
  200. var prefinished = false
  201. dup.on('prefinish', function() {
  202. t.ok(!prefinished, 'only prefinish once')
  203. prefinished = true
  204. })
  205. dup.on('finish', function() {
  206. t.end()
  207. })
  208. dup.end()
  209. })
  210. tape('close', function(t) {
  211. var passthrough = through()
  212. var dup = duplexify(passthrough, passthrough)
  213. passthrough.emit('close')
  214. dup.on('close', function() {
  215. t.ok(true, 'should forward close')
  216. t.end()
  217. })
  218. })
  219. tape('works with node native streams (net)', function(t) {
  220. t.plan(1)
  221. var server = net.createServer(function(socket) {
  222. var dup = duplexify(socket, socket)
  223. dup.once('data', function(chunk) {
  224. t.same(chunk, HELLO_WORLD)
  225. server.close()
  226. socket.end()
  227. t.end()
  228. })
  229. })
  230. server.listen(0, function () {
  231. var socket = net.connect(server.address().port)
  232. var dup = duplexify(socket, socket)
  233. dup.write(HELLO_WORLD)
  234. })
  235. })