├── example
├── skates
│ ├── '
│ ├── client.js
│ ├── index.html
│ ├── server.js
│ └── simple.js
└── socket.io
│ ├── client.js
│ ├── index.html
│ ├── server.js
│ └── simple.js
├── index.js
├── package.json
├── readme.markdown
└── test
├── consistent.js
├── disconnections.js
└── simple.js
/example/skates/':
--------------------------------------------------------------------------------
1 | var skates = require('skates')
2 | var connect = require('connect')
3 | var _bs = require('browser-stream')
4 | var assert = require('assert')
5 | var es = require('event-stream')
6 |
7 | var app = skates()
8 | .use(connect.static(__dirname))
9 | .on('connection', function (sock) {
10 | sock.on('ping', function () {
11 | console.log('ping')
12 | sock.emit('pong')
13 | })
14 | var bs = _bs(sock)
15 | bs.on('connection', function (stream) {
16 | console.log('STREAM OPTIONS', stream)
17 | //stream.pipe(es.stringify()).pipe(es.log())
18 | var i = 0
19 | var t
20 | t = setInterval(function () {
21 | stream.write({item: ++i})
22 | console.log(i)
23 | /* if(i < 21)
24 | return
25 | stream.end()*/
26 | // clearInterval(t, 200)
27 | }, 500)
28 | stream.on('end', function (){
29 | clearInterval(t)
30 | })
31 | })
32 | })
33 | .listen(3000, function () {
34 | console.log('BrowserStream example running on port 3000')
35 | })
36 |
--------------------------------------------------------------------------------
/example/skates/client.js:
--------------------------------------------------------------------------------
1 | //var io = require('socket.io')
2 | skates = require('skates')()
3 | var bs = require('browser-stream')(skates)
4 |
5 | ping = function () {
6 | skates.emit('ping')
7 | }
8 |
9 | skates.on('pong', function () {
10 | console.log('pong')
11 | })
12 |
13 | skates.on('flow', function (s, r) {
14 | if(s || r)
15 | console.log('flow', s, r)
16 | })
17 | console.log('MODULE')
18 | require('domready')(function () {
19 | console.log('DOMREADY')
20 | function sync () {
21 | console.log('SYNC!')
22 | //remember, you have to recreate your streams after they have closed
23 | var domnode = require('domnode')('#body', '{{item}} ')
24 | rs = bs.createReadStream('whatever',
25 | {options: true, random: Math.random()})
26 |
27 | rs.pipe(domnode)
28 | rs.on('end', function () {
29 | rs.removeAllListeners()
30 | sync()
31 | })
32 | }
33 | sync()
34 |
35 | })
36 |
--------------------------------------------------------------------------------
/example/skates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/example/skates/server.js:
--------------------------------------------------------------------------------
1 | var skates = require('skates')
2 | var connect = require('connect')
3 | var _bs = require('browser-stream')
4 | var assert = require('assert')
5 | var es = require('event-stream')
6 |
7 | var app = skates()
8 | .use(connect.static(__dirname))
9 | .on('connection', function (sock) {
10 | sock.on('ping', function () {
11 | console.log('ping')
12 | sock.emit('pong')
13 | })
14 | var bs = _bs(sock)
15 | bs.on('connection', function (stream) {
16 | console.log('STREAM OPTIONS', stream)
17 | //stream.pipe(es.stringify()).pipe(es.log())
18 | var i = 0
19 | var t
20 | t = setInterval(function () {
21 | stream.write({item: ++i})
22 | console.log(i)
23 | /* if(i < 21)
24 | return
25 | stream.end()*/
26 | // clearInterval(t, 200)
27 | }, 500)
28 | stream.on('close', function (){
29 | clearInterval(t)
30 | })
31 | stream.on('error', function () {})
32 | })
33 | })
34 | .listen(3000, function () {
35 | console.log('BrowserStream example running on port 3000')
36 | })
37 |
--------------------------------------------------------------------------------
/example/skates/simple.js:
--------------------------------------------------------------------------------
1 | //am having trouble getting socket.io to work.
2 |
3 |
4 | var sio = require('socket.io')
5 | var http = require('http')
6 | var server = http.createServer(function (req, res) {
7 |
8 | res.end('HELLO')
9 | })
10 | sio.listen(server)
11 | server.listen(3000)
12 |
13 |
--------------------------------------------------------------------------------
/example/socket.io/client.js:
--------------------------------------------------------------------------------
1 | //var io = require('socket.io')
2 | var bs = require('browser-stream')(io.connect('http://localhost:3000'))
3 |
4 | var domnode = require('domnode')('#body', '{{item}}
')
5 |
6 | rs = bs.createStream('whatever',
7 | {options: true, random: Math.random()})
8 |
9 | rs.pipe(domnode)
10 |
11 | rs.on('data', function(d) {
12 | console.log('>>>', d)
13 | })
14 |
15 | rs.write('hello')
16 | rs.write('goodbye')
17 |
--------------------------------------------------------------------------------
/example/socket.io/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/example/socket.io/server.js:
--------------------------------------------------------------------------------
1 | var io = require('socket.io')
2 | var connect = require('connect')
3 | var app = connect.createServer()
4 | var http = require('http')
5 | var io = require('socket.io')
6 | var _bs = require('browser-stream')
7 | var assert = require('assert')
8 | var browserify = require('browserify')
9 | var es = require('event-stream')
10 | var fs = require('fs')
11 | //TODO: allow both _bs(io) and _bs(connection)
12 |
13 | app = app
14 | .use(connect.static(__dirname))
15 | .use(browserify({entry: __dirname+'/client.js', cache: true}))
16 |
17 | io = io.listen(app.listen(3000, function () {
18 | console.log('BrowserStream example running on port 3000')
19 | }))
20 |
21 | io.on('connection', function (sock) {
22 | var bs = _bs(sock)
23 | bs.on('connection', function (stream) {
24 | stream.pipe(es.stringify()).pipe(es.log())
25 | var i = 0
26 | var t
27 | t = setInterval(function () {
28 | stream.write({item: ++i})
29 | if(i < 21)
30 | return
31 | stream.end()
32 | clearInterval(t, 200)
33 | })
34 | })
35 | })
36 |
37 |
38 |
--------------------------------------------------------------------------------
/example/socket.io/simple.js:
--------------------------------------------------------------------------------
1 | //am having trouble getting socket.io to work.
2 |
3 |
4 | var sio = require('socket.io')
5 | var http = require('http')
6 | var server = http.createServer(function (req, res) {
7 |
8 | res.end('HELLO')
9 | })
10 | sio.listen(server)
11 | server.listen(3000)
12 |
13 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 |
2 | var Stream = require('stream').Stream
3 | var EventEmitter = require('events').EventEmitter
4 |
5 | /*
6 | Although sockjs and browserchannel are consistent on the client
7 | they are different on the server, while socket.io are consistent on the client and the server...
8 |
9 | I wrote a module that wraps sockjs (could easily adapt to wrap any WebSocket Compatibility Layer)
10 | in an interface that is like an two remote event emitters,
11 | except that A.on('event',listener) is triggered by B.emit('event')
12 |
13 | (see the tests)
14 |
15 |
16 |
17 | */
18 |
19 | module.exports = function (sock) {
20 |
21 | var streams = {}
22 | /*
23 | socket.io is a bad pattern. it's a single lib,
24 | but it _should_ be a small ecosystem of tools.
25 |
26 | when you call createStream() it should return a stream immediately.
27 | thats how it is everywhere else in node.
28 |
29 | but, if there is a disconnection, all the streams should emit 'end'.
30 | then emit 'error' if you try to write to them after?
31 |
32 | my problem wasn't in socket.io... it was in browser-stream.
33 | */
34 |
35 | var e = new EventEmitter ()
36 | var count = 1
37 | var DATA = ''
38 | , END = '.'
39 | , PAUSE = '?'
40 | , RESUME = '*'
41 | , ERROR = '!'
42 |
43 | function _createStream(opts) {
44 | var s = new Stream(), ended = false
45 | //if either w or r is false, def will be false
46 | var def = !opts.writable && !opts.readable
47 | s.readable = opts.readable || def
48 | s.writable = opts.writable || def
49 | if(opts.opts || opts.options)
50 | s.options = opts.opts || opts.options
51 | s.name = opts.name
52 | //if(streams[opts.name])
53 | //throw new Error('stream with name "'+opts.name + '" already exists')
54 | streams[opts.name] = true
55 |
56 | s._id = opts._id || count ++
57 |
58 | function onPause () {
59 | s.paused = true
60 | }
61 |
62 | function onResume () {
63 | s.paused = false
64 | s.emit('drain')
65 | }
66 |
67 | function cleanup () {
68 | s.writable = s.readable = false
69 | delete streams[s.name]
70 | sock.removeListener(PAUSE + id, onPause)
71 | sock.removeListener(RESUME + id, onResume)
72 | sock.removeListener(DATA + id, onData)
73 | sock.removeListener(END + id, onEnd)
74 | sock.removeListener('disconnect', onDisconnect)
75 | }
76 |
77 | function onDisconnect () {
78 | if(!ended) {
79 | s.emit('error', new Error('unexpected disconnection (call end() first)'))
80 | cleanup()
81 | }
82 | ended = true
83 | }
84 |
85 | sock.on('disconnect', onDisconnect)
86 |
87 | function onData(data) {
88 | s.emit('data', data)
89 | }
90 |
91 | function onEnd () {
92 | if(!ended) {
93 | s.emit('end')
94 | cleanup()
95 | }
96 | }
97 |
98 | s.destroy = function () {
99 | ended = true
100 | cleanup()
101 | s.emit('close')
102 | }
103 |
104 | if(s.writable) {
105 | var id = s._id
106 | s.write = function (data) {
107 | if(ended) throw new Error('write to ended stream')
108 | sock.emit(DATA + id, data)
109 | return !s.paused
110 | }
111 |
112 | s.end = function (data) {
113 | if(data != null) this.write(data)
114 | if(!ended) sock.emit(END + id)
115 | s.destroy()
116 | }
117 |
118 | sock.on(PAUSE + id, onPause)
119 | sock.on(RESUME + id, onResume)
120 |
121 | //TODO but remember, some errors are circular.
122 | //sock.on(ERROR + id, function (error) {
123 | // s.emit('error', error)
124 | //}
125 |
126 | }
127 |
128 | if(s.readable) {
129 | var id = s._id
130 | s.readable = true
131 | sock.on(DATA + id, onData)
132 | sock.on(END + id, onEnd)
133 |
134 | s.pause = function () {
135 | s.paused = true
136 | if(ended) return
137 | sock.emit(PAUSE + id)
138 | }
139 |
140 | s.resume = function () {
141 | s.paused = false
142 | if(ended) return
143 | sock.emit(RESUME + id)
144 | }
145 | } //end of setting up readable stream
146 |
147 | return s
148 | }
149 |
150 | e.createWriteStream = function (name, opts) {
151 | return this.createStream(name, opts, {writable: true})
152 | }
153 |
154 | e.createReadStream = function (name, opts) {
155 | return this.createStream(name, opts, {readable: true})
156 | }
157 |
158 | e.createStream = function (name, opts, settings) {
159 | settings = settings || {}
160 | settings.name = name
161 | settings.options = opts
162 |
163 | var s = _createStream(settings) //defaults to readable and writable
164 | var _opts = {name: name, _id: s._id}
165 | if(opts) {
166 | _opts.options = opts
167 | s.options = opts
168 | }
169 |
170 | if(s.readable)
171 | _opts.writable = true
172 | if(s.writable)
173 | _opts.readable = true
174 | sock.emit('CREATE_STREAM', _opts)
175 | return s
176 | }
177 |
178 | sock.on('CREATE_STREAM', function (settings) {
179 | var s = _createStream(settings)
180 | e.emit('connection', s, settings.options)
181 | })
182 |
183 | return e
184 | }
185 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": "Dominic Tarr (dominictarr.com)",
3 | "name": "browser-stream",
4 | "description": "pipe streams through Socket.io",
5 | "version": "0.1.10",
6 | "homepage": "https://github.com/dominictarr/browser-stream",
7 | "repository": {
8 | "type": "git",
9 | "url": "git://github.com/dominictarr/browser-stream.git"
10 | },
11 | "engines": {
12 | "node": "0.6"
13 | },
14 | "dependencies": {
15 | "event-stream": "~2.0.0"
16 | },
17 | "devDependencies": {
18 | "socket.io": "0.9",
19 | "express": "2.5",
20 | "domnode": "0",
21 | "browserify": "~1.13",
22 | "domready": "~0.2.11",
23 | "skates": "0.0.1",
24 | "tap": "~0.2.5",
25 | "remote-events": "0.0.0"
26 | },
27 | "scripts": {
28 | "test": "tap test/*.js"
29 | },
30 | "optionalDependencies": {}
31 | }
32 |
--------------------------------------------------------------------------------
/readme.markdown:
--------------------------------------------------------------------------------
1 | # BrowserStream
2 |
3 | use `Stream#pipe` to send data to clients or servers.
4 |
5 | wrap `socket.io` (or another web socket abstraction that gives a remote `EventEmitter` api)
6 | with a interface for creating streams.
7 |
8 | ### DEPRECIATED
9 |
10 | use [mux-demux](http://github.com/dominictarr/mux-demux) with [shoe](http://github.com/substack/shoe)
11 |
12 | I'm not gonna use or maintain this any more. If you want to use and maintain this module email me and I'll
13 | add you as owner.
14 |
15 | ## install
16 |
17 | ```
18 | npm install browser-stream
19 |
20 | ```
21 |
22 | ## example
23 |
24 | ### client
25 |
26 | ``` js
27 | var bs = require('browser-stream')(io.connect('http://localhost:3000'))
28 | var domnode = require('domnode') //see https://github.com/maxogden/dominode
29 | var opts = {options: 'pass an optional object with the createReadStream message. maybe useful!'})
30 | //pipe the 'whatever' stream to the dom with dominode.
31 | bs.createReadStream('whatever', options)
32 | .on('error', function (err) {
33 | //unexpected disconnect
34 | console.error(err)
35 | })
36 | .pipe(domnode('#list', ''))
37 |
38 | ```
39 |
40 | ### server
41 |
42 | ``` js
43 |
44 | io = io.listen(app) //see https://github.com/LearnBoost/socket.io
45 | var _bs = require('browser-stream')
46 |
47 | io.sockets.on('connection', function (sock) {
48 |
49 | var bs = _bs(sock)
50 |
51 | var whatever = new Stream() // SOME KIND OF STREAM
52 | bs.on('connection', function (stream, opts) {
53 | if(stream.name == 'whatever')
54 | whatever.pipe(stream)
55 | //stream.options -- will be the same as `opts` from the client side!
56 | stream.on('error', function (err) {
57 | //the client has unexpectedly disconnected. tidy up!
58 | console.error(err)
59 | })
60 | })
61 |
62 | }
63 |
64 | ```
65 |
66 | this will connect `whatever` to the `Dominode` stream, rendering it, in the browser!
67 |
68 | ## API
69 |
70 | ``` js
71 |
72 | var _bs = require('browser-stream')
73 |
74 | io.sockets.on('connection', function (sock) {
75 | var bs = _bs(sock)
76 | bs.on('connection', function (stream) {
77 | //stream is a pipable node.js `Stream` instance
78 | })
79 | })
80 |
81 | ```
82 |
83 | ### createReadStream (name, options)
84 |
85 |
86 |
87 | open a `ReadableStream` from the other side.
88 | returns a `ReadableStream`.
89 | the other side of connection will emit a writable stream that is connected to this stream.
90 |
91 | ### createWriteStream (name, options)
92 |
93 | open a `WritableStream` to the other side.
94 | returns a `WritableStream`, the other side will emit a `ReadableStream` connected to this stream.
95 |
96 | ### createStream (name, options)
97 |
98 | open a `Stream` to the other side which is both readable and writable.
99 | returns a `Stream`, the other side will emit a `Stream` connected to this stream.
100 |
101 | > note to self, references to a class (`Stream`) should be capitalized, and in backticks.
102 | > references to an instance should be lowercase, and not in backticks unless refuring to
103 | > a specific variable in a code example.
104 |
--------------------------------------------------------------------------------
/test/consistent.js:
--------------------------------------------------------------------------------
1 | var es = require('event-stream')
2 | var a = require('assertions')
3 |
4 | module.exports =
5 | function consistent(test) {
6 | test = test || a.deepEqual
7 | var stream = es.through()
8 | var chunks = 0
9 | stream.on('data', function () {
10 | chunks ++
11 | })
12 | stream.createSlave = function () {
13 | var expected = [], count = 0, ended = false
14 | stream.on('data', function (data) {
15 | expected.push(data)
16 | })
17 | var slave = es.through()
18 | slave.on('data', function (data) {
19 | a.greaterThan(expected.length, 0, 'slave stream did not expect write')
20 | a.equal(ended, false, 'slave expected stream not to have ended')
21 | var next = expected.shift()
22 | count ++
23 | test(next, data)
24 | })
25 | //it's okay to pass data to end(data)
26 | //but never emit('end', data)
27 | slave.on('end', function () {
28 | ended = true
29 | a.equal(expected.length, 0, 'slave stream expected 0 more writes')
30 | })
31 | slave.validate = function (message) {
32 | a.equal(count, chunks, 'slave must recieve same number of chunks as master')
33 | a.ok(count)
34 | }
35 | return slave
36 | }
37 | return stream
38 | }
39 |
--------------------------------------------------------------------------------
/test/disconnections.js:
--------------------------------------------------------------------------------
1 | /*
2 |
3 | connect two streams.
4 |
5 | on a disconnect, both streams should emit 'close'
6 |
7 | */
8 |
9 | var a = require('assertions')
10 | var RemoteEventEmitter = require('remote-events')
11 | var consistent = require('./consistent')
12 | var bs = require('..')
13 | var es = require('event-stream')
14 |
15 | function randomNumberStream (max, count) {
16 | count = count || 20
17 | max = max || 10
18 | return es.readable(function (i, cb) {
19 | this.emit('data', Math.random() * max)
20 | if(i > count)
21 | this.emit('end')
22 | cb()
23 | })
24 | }
25 |
26 | ;(function () {
27 |
28 | var master = consistent()
29 | var slave = master.createSlave()
30 |
31 | var _client = new RemoteEventEmitter()
32 | var _server = new RemoteEventEmitter()
33 |
34 | _client.getStream().pipe(_server.getStream()).pipe(_client.getStream())
35 | var client = bs(_client)
36 | var server = bs(_server)
37 | var count = 0, dCount = 1
38 | server.on('connection', function (stream) {
39 | a.equal(stream.name, 'disconnect1')
40 | stream
41 | .on('error', function () {
42 | console.log('<< ERROR')
43 | })
44 | .pipe(slave)
45 | .pipe(es.log('<<'))//.pipe(stream)
46 | .on('data', function () {
47 | dCount ++
48 | })
49 | .on('end', function () {
50 | a.equal(count, dCount, 'each stream should see the same items')
51 | console.log('<< END')
52 | })
53 | })
54 | var rns = randomNumberStream()
55 | rns
56 | .on('data', function (data) {
57 | if(++ count < 12) return
58 | if(_client.connected) {
59 | _client.disconnect()
60 | console.log('DISCONNECT')
61 | }
62 | console.log('DATA', data, count)
63 | })
64 | .pipe(master)
65 | .pipe(es.log('>>'))
66 | .pipe(client.createWriteStream('disconnect1')
67 | .on('error', function () {rns.destroy(); console.log('>> ERROR')})
68 | .on('end', function () {
69 | //END should always be EMITTED
70 | //RIGHT?
71 | a.equal(count, dCount, 'each stream should see the same items')
72 | console.log('>> END')
73 | //not all the events are emitted,
74 | //but since the streams are destroyed,
75 | //and piping stops then they end up with
76 | //the same data through them.
77 | slave.validate()
78 | }))
79 | /*
80 | THERE are some problems with streams that close.
81 | or rather, SHOULD close.
82 | */
83 |
84 | })();
85 |
86 |
87 | ;(function simple () {
88 |
89 | var _client = new RemoteEventEmitter()
90 | var _server = new RemoteEventEmitter()
91 | _client.getStream().pipe(_server.getStream()).pipe(_client.getStream())
92 |
93 | var client = bs(_client)
94 | var server = bs(_server)
95 |
96 | var r1 = Math.random()
97 | server.on('connection', function (stream) {
98 | stream.on('data', function (data) {
99 | a.equal(data, r1)
100 | console.log('data')
101 | })
102 | stream.on('end', function () {
103 | console.log('end')
104 | })
105 | })
106 |
107 | c = client.createWriteStream()
108 | c.write(r1)
109 | c.end()
110 |
111 | })();
112 |
113 | ;(function disconnect () {
114 |
115 | var _client = new RemoteEventEmitter()
116 | var _server = new RemoteEventEmitter()
117 | _client.getStream().pipe(_server.getStream()).pipe(_client.getStream())
118 |
119 | _client.on('disconnect', function () {
120 | console.log('CLIENT DISCONNECT')
121 | })
122 | _server.on('disconnect', function () {
123 | console.log('SERVER DISCONNECT')
124 | })
125 | var client = bs(_client)
126 | var server = bs(_server)
127 |
128 | var randoms = []
129 | function rand() {
130 | var r
131 | randoms.push(r = Math.random())
132 | return r
133 | }
134 | var clientErr = false, serverErr = false
135 | process.on('exit', function () {
136 | a.ok(clientErr, 'expected client to emit an error')
137 | a.ok(serverErr, 'expected server to emit an error')
138 | console.log('end point emitted errors correctly')
139 | })
140 |
141 | var streams = 0, ended = 0
142 | server.on('connection', function (stream) {
143 | streams ++
144 | stream
145 | .on('data', function (data) {
146 | var r
147 | a.equal(data, r = randoms.shift())
148 | console.log('data', r)
149 | })
150 | .on('error', function () {
151 | //I'm expecting this
152 | serverErr = true
153 | a.equal(streams, 1)
154 | console.log('error!')
155 | })
156 | var r = Math.random()
157 | var _ended = false
158 | stream.on('end', function () {
159 | a.ok(!_ended, 'end MUST only be emitted once')
160 | _ended = true
161 | a.equal(streams, ++ ended)
162 | console.log('end!')
163 | })
164 | })
165 |
166 | var c = client.createWriteStream('A')
167 | c.on('error', function () {
168 | //expecting this!
169 | clientErr = true
170 | console.log('error')
171 | })
172 |
173 | c.write(rand())
174 | c.write(rand())
175 | c.write(rand())
176 | c.write(rand())
177 | _client.disconnect()
178 |
179 | if(c.writable)
180 | c.write(rand())
181 | a.throws(function () { c.write(rand()) })
182 |
183 | })();
184 |
185 |
186 | ;(function disconnect2 () {
187 | console.log('disconnect2')
188 | var _client = new RemoteEventEmitter()
189 | var _server = new RemoteEventEmitter()
190 |
191 | var client = bs(_client)
192 | var server = bs(_server)
193 |
194 | var randoms = []
195 | function rand() {
196 | var r
197 | randoms.push(r = Math.random())
198 | return r
199 | }
200 | var streams = 0
201 | server.on('connection', function (s) {
202 | s.write(rand())
203 | s.write(rand())
204 | s.write(rand())
205 | s.write(rand())
206 | s.end()
207 | a.throws(function () { s.write(Math.random()) })//this should be ignored
208 | })
209 |
210 | c = client.createReadStream()
211 | c.on('data', function (data) {
212 | var r
213 | a.equal(data, r = randoms.shift())
214 | console.log('data', r)
215 | })
216 | .on('end', function () {
217 | console.log('end')
218 | })
219 | _client.getStream().pipe(_server.getStream()).pipe(_client.getStream())
220 |
221 | })();
222 |
--------------------------------------------------------------------------------
/test/simple.js:
--------------------------------------------------------------------------------
1 |
2 | var a = require('assertions')
3 | var RemoteEventEmitter = require('remote-events')
4 | var consistent = require('./consistent')
5 | var es = require('event-stream')
6 | var _bs = require('..')
7 |
8 | /*
9 | socket.io behaves like two linked EventEmitters.
10 | calling emit on one, triggers listeners on the other.
11 |
12 | (see RemoteEventEmitter)
13 |
14 | test that two streams match.
15 |
16 | create a master stream and slave streams,
17 | assert that every chunk written to the master
18 | is eventually written to the slave.
19 |
20 | OKAY, my disconnection error is in HERE
21 | somewhere in here, things are breaking after reconnecting.
22 | what is it?
23 |
24 |
25 | */
26 |
27 |
28 | function pair(f) {
29 | var a = new RemoteEventEmitter()
30 | var b = new RemoteEventEmitter()
31 | a.getStream().pipe(b.getStream()).pipe(a.getStream())
32 |
33 | return [a, b]
34 | }
35 |
36 | function randomNumberStream (max, count) {
37 | count = count || 20
38 | max = max || 10
39 | return es.readable(function (i, cb) {
40 | this.emit('data', Math.random() * max)
41 | if(i > count)
42 | this.emit('end')
43 | cb()
44 | })
45 | }
46 |
47 | ;(function simple () {
48 |
49 | var p = pair()
50 | var server = _bs(p.pop())
51 | var client = _bs(p.pop())
52 |
53 | var master = consistent()
54 | var slave = master.createSlave()
55 |
56 | server.on('connection', function (stream) {
57 | a.equal(stream.name, 'simple')
58 | stream
59 | .pipe(slave)
60 | })
61 |
62 | randomNumberStream()
63 | .pipe(master)
64 | .pipe(client.createWriteStream('simple'))
65 |
66 | process.on('exit', slave.validate)
67 |
68 | })();
69 |
70 | //return
71 | ;(function through () {
72 |
73 | var p = pair()
74 | var server = _bs(p.shift())
75 | var client = _bs(p.shift())
76 |
77 | var master = consistent()
78 | var slave1 = master.createSlave()
79 | var slave2 = master.createSlave()
80 |
81 | server.on('connection', function (stream) {
82 | a.equal(stream.name, 'through')
83 | stream.pipe(slave1).pipe(stream) //ECHO
84 | })
85 |
86 | randomNumberStream()
87 | .pipe(master)
88 | .pipe(client.createStream('through'))
89 | .pipe(slave2)
90 | .on('end', function () {
91 | slave1.validate()
92 | slave2.validate()
93 | console.log('slave 1,2 valid')
94 | })
95 |
96 | })();
97 |
98 |
99 | // names do not have to be unique.
100 | // should create two seperate streams.
101 |
102 |
103 | ;(function double () {
104 | var p = pair()
105 | var server = _bs(p.shift())
106 | var client = _bs(p.shift())
107 |
108 | var master1 = consistent()
109 | var slave1 = master1.createSlave()
110 | var master2 = consistent()
111 | var slave2 = master2.createSlave()
112 |
113 | server.on('connection', function (stream) {
114 | a.equal(stream.name, 'through')
115 | stream.pipe(stream) //ECHO
116 | })
117 |
118 | randomNumberStream()
119 | .pipe(master1)
120 | .pipe(client.createStream('through'))
121 | .pipe(slave1)
122 | .on('end', function () {
123 | slave1.validate()
124 | console.log('slave1 valid')
125 | })
126 |
127 | //okay! this is breaking
128 | randomNumberStream()
129 | .pipe(master2)
130 | .pipe(client.createStream('through'))
131 | .pipe(slave2)
132 | .on('end', function () {
133 | slave2.validate()
134 | console.log('slave2 valid')
135 | })
136 | })();
137 |
138 | /*
139 | since I'm here, I may as well implement pausing
140 | etc.
141 |
142 | pass through pause, so that it can be used
143 | to control stuff like scrolling.
144 | */
145 |
146 | /*
147 | if a function respects pause, that means that on pause(),
148 | the next write should return false.
149 |
150 | then, on resume() the next write should return true
151 |
152 | this case is pretty simple.
153 | */
154 |
155 | ;(function passesPauseThrough(stream) {
156 | var p = pair()
157 | var server = _bs(p.pop())
158 | var client = _bs(p.pop())
159 |
160 | server.on('connection', function (stream) {
161 | a.equal(stream.name, 'paused')
162 | stream
163 | var i = 0
164 | stream.on('data', function () {
165 | if(i++ % 2)
166 | stream.pause()
167 | else //if (stream.paused)
168 | stream.resume()
169 | })
170 | })
171 |
172 | master = (client.createWriteStream('paused'))
173 |
174 | a.equal(master.write('hello'), true, 'should be free')
175 | a.equal(master.write('paused now'), false, 'should be paused')
176 | a.equal(master.write('hello'), true, 'should be free2')
177 | a.equal(master.write('paused now'), false, 'should be paused')
178 |
179 | master.end()
180 | console.log('pause is correct')
181 | })();
182 |
183 |
--------------------------------------------------------------------------------