Files: d5c6f9521130fcae13928a86e3f39d88e2586342 / test / random.js
7730 bytesRaw
1 | |
2 | var pull = require('pull-stream') |
3 | var paramap = require('pull-paramap') |
4 | var ssbKeys = require('ssb-keys') |
5 | var u = require('./util') |
6 | |
7 | var tape = require('tape') |
8 | |
9 | var cats = require('cat-names') |
10 | var dogs = require('dog-names') |
11 | |
12 | var generated = {}, F=100,N=10000 |
13 | |
14 | //build a random network, with n members. |
15 | function bar (prog) { |
16 | var r = prog.progress/prog.total |
17 | var s = '\r', M = 50 |
18 | for(var i = 0; i < M; i++) |
19 | s += i < M*r ? '*' : '.' |
20 | |
21 | return s + ' '+prog.progress+'/'+prog.total+' '//+':'+prog.feeds |
22 | } |
23 | |
24 | function isNumber (n) { |
25 | return typeof n === 'number' |
26 | } |
27 | |
28 | function once (fn) { |
29 | var called = false |
30 | return function () { |
31 | if(called) throw new Error('called twice!') |
32 | called = true |
33 | fn.apply(this, arguments) |
34 | } |
35 | } |
36 | |
37 | var createSbot = require('../') |
38 | .use(require('../plugins/replicate')) |
39 | .use(require('ssb-friends')) |
40 | .use(require('ssb-ebt')) |
41 | .use(require('../plugins/gossip')) |
42 | |
43 | function generateAnimals (sbot, feed, f, n, cb) { |
44 | var a = [feed] |
45 | |
46 | while(f --> 0) |
47 | a.push(sbot.createFeed()) |
48 | |
49 | console.log('generate NAMES') |
50 | |
51 | pull( |
52 | pull.values(a), |
53 | paramap(function (feed, cb) { |
54 | var animal = Math.random() > 0.5 ? 'cat' : 'dog' |
55 | var name = animal == 'cat' ? cats.random() : dogs.allRandom() |
56 | |
57 | feed.name = name |
58 | feed.add(u.follow(feed.id), cb) |
59 | }, 10), |
60 | pull.drain(null, function (err) { |
61 | if(err) return cb(err) |
62 | |
63 | var posts = [] |
64 | |
65 | pull( |
66 | pull.count(n), |
67 | paramap(function (n, cb) { |
68 | |
69 | var me = a[~~(Math.random()*a.length)] |
70 | var r = Math.random() |
71 | |
72 | //one in 20 messages is a random follow |
73 | if(r < 0.5) { |
74 | var f = a[~~(Math.random()*a.length)] |
75 | me.add(u.follow(f.id), cb) |
76 | } else if(r < 0.6) { |
77 | me.add({ |
78 | type: 'post', |
79 | text: me.animal === 'dog' ? 'woof' : 'meow', |
80 | }, function (err, msg) { |
81 | posts.push(msg.key) |
82 | if(posts.length > 100) |
83 | posts.shift() |
84 | cb(null, msg) |
85 | }) |
86 | } else { |
87 | var post = posts[~~(Math.random()*posts.length)] |
88 | me.add({ |
89 | type: 'post', |
90 | repliesTo: post, |
91 | text: me.animal === 'dog' ? 'woof woof' : 'purr', |
92 | }, function (err, msg) { |
93 | cb(null, msg) |
94 | }) |
95 | |
96 | } |
97 | }, 32), |
98 | pull.drain(null, cb) |
99 | ) |
100 | |
101 | }) |
102 | ) |
103 | |
104 | } |
105 | |
106 | function latest (sbot, cb) { |
107 | sbot.friends.hops({hops: 3}, once(function (err, keys) { |
108 | if(err) return cb(err) |
109 | var n = Object.keys(keys).length, map = {} |
110 | console.log('Generated network:') |
111 | console.log(keys) |
112 | if(n !== F+1) throw new Error('not enough feeds:'+n+', expected:'+(F+1)) |
113 | |
114 | for(var k in keys) (function (key) { |
115 | sbot.latestSequence(key, once(function (err, value) { |
116 | if(err) { |
117 | console.log(key, err, value) |
118 | throw err |
119 | } |
120 | map[key] = isNumber(value) ? value : value.sequence |
121 | if(--n) return |
122 | cb(null, map) |
123 | })) |
124 | })(k) |
125 | })) |
126 | } |
127 | |
128 | var alice = ssbKeys.generate() |
129 | var bob = ssbKeys.generate() |
130 | |
131 | var animalNetwork = createSbot({ |
132 | temp: 'test-random-animals', |
133 | port: 45451, host: 'localhost', timeout: 20001, |
134 | replication: {hops: 3, legacy: false}, keys: alice |
135 | }) |
136 | |
137 | pull( |
138 | animalNetwork.replicate.changes(), |
139 | pull.drain(function (prog) { |
140 | prog.id = 'animal network' |
141 | console.log(prog) |
142 | }) |
143 | ) |
144 | |
145 | |
146 | tape('generate random network', function (t) { |
147 | var start = Date.now() |
148 | generateAnimals(animalNetwork, {add: animalNetwork.publish, id: animalNetwork.id}, F, N, function (err) { |
149 | if(err) throw err |
150 | console.log('replicate GRAPH') |
151 | var c = 0 |
152 | latest(animalNetwork, function (err, _generated) { |
153 | if(err) throw err |
154 | |
155 | generated = _generated |
156 | var total = 0, feeds = 0 |
157 | for(var k in generated) { |
158 | total += generated[k] |
159 | feeds ++ |
160 | } |
161 | |
162 | var time = (Date.now()-start)/1000 |
163 | console.log('generated', total, 'messages in', time, 'at rate:', total/time) |
164 | console.log('over', feeds, 'feeds') |
165 | t.equal(total, N+1+F+1) |
166 | t.equal(feeds, F+1) |
167 | t.end() |
168 | }) |
169 | }) |
170 | }) |
171 | |
172 | tape('read all history streams', function (t) { |
173 | |
174 | var opts = { |
175 | host: 'localhost', port: 45451, |
176 | key: alice.id, |
177 | manifest: animalNetwork.manifest() |
178 | } |
179 | |
180 | var dump = createSbot({ |
181 | temp: 'test-random-animals_dump', |
182 | // port: 45453, host: 'localhost', timeout: 20001, |
183 | keys: bob |
184 | }) |
185 | var live = 0, listeners = 0 |
186 | var since = {} |
187 | |
188 | var h = 0 |
189 | |
190 | pull( |
191 | dump.createLogStream({live: true, keys: false}), |
192 | pull.drain(function (e) { |
193 | if(!(live ++ % 100)) |
194 | console.log('live', live) |
195 | }) |
196 | ) |
197 | |
198 | var wants = {}, n = 0, c = 0, start = Date.now() |
199 | |
200 | //test just dumping everything! |
201 | //not through network connection, because createLogStream is not on public api |
202 | pull( |
203 | animalNetwork.createLogStream({keys: false}), |
204 | pull.through(function (n) { |
205 | c++ |
206 | }), |
207 | dump.createWriteStream(function (err, data) { |
208 | if(err) throw err |
209 | var time = (Date.now() - start)/1000 |
210 | console.log("dump all messages via createLogStream") |
211 | console.log('all histories dumped', c, 'messages in', time, 'at rate', c/time) |
212 | console.log('read back live:', live, 'over', h, 'histories', listeners, 'listeners') |
213 | pull( |
214 | dump.createLogStream(), |
215 | pull.collect(function (err, ary) { |
216 | if(err) throw err |
217 | console.log(c) |
218 | t.equal(ary.length, F+N+2) |
219 | dump.close() |
220 | t.end() |
221 | }) |
222 | ) |
223 | }) |
224 | ) |
225 | |
226 | }) |
227 | |
228 | tape('replicate social network for animals', function (t) { |
229 | //return t.end() |
230 | var c = 0 |
231 | if(!animalNetwork.friends) |
232 | throw new Error('missing frineds plugin') |
233 | |
234 | var start = Date.now() |
235 | var animalFriends = createSbot({ |
236 | temp: 'test-random-animals2', |
237 | port: 45452, host: 'localhost', timeout: 20001, |
238 | replicate: {hops: 3, legacy: false}, |
239 | progress: true, |
240 | seeds: [animalNetwork.getAddress()], |
241 | keys: bob |
242 | }) |
243 | animalFriends.logging |
244 | var connections = 0 |
245 | |
246 | animalFriends.on('rpc:connect', function (rpc) { |
247 | connections++ |
248 | c++ |
249 | console.log("CONNECT", connections) |
250 | rpc.on('closed', function () { |
251 | console.log("DISCONNECT", --connections) |
252 | }) |
253 | }) |
254 | |
255 | var drain |
256 | |
257 | // pull( |
258 | // animalFriends.replicate.changes(), |
259 | // drain = pull.drain(function (prog) { |
260 | // prog.id = 'animal friends' |
261 | // var target = F+N+3 |
262 | // process.stdout.write(bar(prog)) |
263 | // if(prog.progress === target) { |
264 | // console.log("DONE!!!!") |
265 | // var time = (Date.now() - start) / 1000 |
266 | // console.log('replicated', target, 'messages in', time, 'at rate',target/time) |
267 | // t.equal(c, 1, 'everything replicated within a single connection') |
268 | // animalFriends.close(true) |
269 | // drain.abort() |
270 | // t.end() |
271 | // } |
272 | // }) |
273 | // ) |
274 | |
275 | require('../lib/progress')(animalFriends.progress) |
276 | |
277 | var int = setInterval(function () { |
278 | var prog = animalFriends.progress() |
279 | if(prog.ebt && prog.ebt.current === prog.ebt.target) { |
280 | var target = F+N+3 |
281 | var time = (Date.now() - start) / 1000 |
282 | console.log('replicated', target, 'messages in', time, 'at rate',target/time) |
283 | clearInterval(int) |
284 | t.equal(c, 1, 'everything replicated within a single connection') |
285 | animalFriends.close(true) |
286 | t.end() |
287 | } |
288 | }, 200) |
289 | |
290 | animalFriends.logging = true |
291 | |
292 | if(!animalFriends.friends) |
293 | throw new Error('missing friends plugin') |
294 | |
295 | animalFriends.publish({ |
296 | type: 'contact', |
297 | contact: animalNetwork.id, |
298 | following: true |
299 | }, function (err, msg) { |
300 | if(err) throw err |
301 | }) |
302 | |
303 | }) |
304 | |
305 | |
306 | tape('shutdown', function (t) { |
307 | animalNetwork.close(true) |
308 | t.end() |
309 | }) |
310 | |
311 | |
312 | |
313 | |
314 | |
315 | |
316 | |
317 | |
318 |
Built with git-ssb-web