Files: 62eb750647d7445ec220135de7f1f5fb1bbadd26 / test / random.js
7124 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 | var ssbClient = require('ssb-client') |
7 | |
8 | var tape = require('tape') |
9 | |
10 | var cats = require('cat-names') |
11 | var dogs = require('dog-names') |
12 | |
13 | var generated = {}, F=100,N=10000 |
14 | |
15 | |
16 | //build a random network, with n members. |
17 | function bar (prog) { |
18 | var r = prog.progress/prog.total |
19 | var s = '\r', M = 50 |
20 | for(var i = 0; i < M; i++) |
21 | s += i < M*r ? '*' : '.' |
22 | |
23 | return s + ' '+prog.progress+'/'+prog.total+' '//+':'+prog.feeds |
24 | } |
25 | |
26 | function isNumber (n) { |
27 | return typeof n === 'number' |
28 | } |
29 | |
30 | function once (fn) { |
31 | var called = false |
32 | return function () { |
33 | if(called) throw new Error('called twice!') |
34 | called = true |
35 | fn.apply(this, arguments) |
36 | } |
37 | } |
38 | |
39 | var createSbot = require('../') |
40 | .use(require('../plugins/replicate')) |
41 | .use(require('ssb-friends')) |
42 | .use(require('../plugins/gossip')) |
43 | |
44 | function generateAnimals (sbot, feed, f, n, cb) { |
45 | var a = [feed] |
46 | |
47 | while(f --> 0) |
48 | a.push(sbot.createFeed()) |
49 | |
50 | console.log('generate NAMES') |
51 | |
52 | pull( |
53 | pull.values(a), |
54 | paramap(function (feed, cb) { |
55 | var animal = Math.random() > 0.5 ? 'cat' : 'dog' |
56 | var name = animal == 'cat' ? cats.random() : dogs.allRandom() |
57 | |
58 | feed.name = name |
59 | feed.add(u.follow(feed.id), cb) |
60 | }, 10), |
61 | pull.drain(null, function (err) { |
62 | if(err) return cb(err) |
63 | |
64 | var posts = [] |
65 | |
66 | pull( |
67 | pull.count(n), |
68 | paramap(function (n, cb) { |
69 | |
70 | var me = a[~~(Math.random()*a.length)] |
71 | var r = Math.random() |
72 | |
73 | //one in 20 messages is a random follow |
74 | if(r < 0.5) { |
75 | var f = a[~~(Math.random()*a.length)] |
76 | me.add(u.follow(f.id), cb) |
77 | } else if(r < 0.6) { |
78 | me.add({ |
79 | type: 'post', |
80 | text: me.animal === 'dog' ? 'woof' : 'meow', |
81 | }, function (err, msg) { |
82 | posts.push(msg.key) |
83 | if(posts.length > 100) |
84 | posts.shift() |
85 | cb(null, msg) |
86 | }) |
87 | } else { |
88 | var post = posts[~~(Math.random()*posts.length)] |
89 | me.add({ |
90 | type: 'post', |
91 | repliesTo: post, |
92 | text: me.animal === 'dog' ? 'woof woof' : 'purr', |
93 | }, function (err, msg) { |
94 | cb(null, msg) |
95 | }) |
96 | |
97 | } |
98 | }, 32), |
99 | pull.drain(null, cb) |
100 | ) |
101 | |
102 | }) |
103 | ) |
104 | |
105 | } |
106 | |
107 | function latest (sbot, cb) { |
108 | sbot.friends.hops({hops: 3}, once(function (err, keys) { |
109 | if(err) return cb(err) |
110 | var n = Object.keys(keys).length, map = {} |
111 | console.log('Generated network:') |
112 | console.log(keys) |
113 | if(n !== F+1) throw new Error('not enough feeds:'+n+', expected:'+(F+1)) |
114 | |
115 | for(var k in keys) (function (key) { |
116 | sbot.latestSequence(key, once(function (err, value) { |
117 | if(err) { |
118 | console.log(key, err, value) |
119 | throw err |
120 | } |
121 | map[key] = isNumber(value) ? value : value.sequence |
122 | if(--n) return |
123 | cb(null, map) |
124 | })) |
125 | })(k) |
126 | })) |
127 | } |
128 | |
129 | var alice = ssbKeys.generate() |
130 | var bob = ssbKeys.generate() |
131 | |
132 | var animalNetwork = createSbot({ |
133 | temp: 'test-random-animals', |
134 | port: 45451, host: 'localhost', timeout: 20001, |
135 | replication: {hops: 3}, keys: alice |
136 | }) |
137 | |
138 | pull( |
139 | animalNetwork.replicate.changes(), |
140 | pull.drain(function (prog) { |
141 | prog.id = 'animal network' |
142 | console.log(prog) |
143 | }) |
144 | ) |
145 | |
146 | |
147 | tape('generate random network', function (t) { |
148 | var start = Date.now() |
149 | generateAnimals(animalNetwork, {add: animalNetwork.publish, id: animalNetwork.id}, F, N, function (err) { |
150 | if(err) throw err |
151 | console.log('replicate GRAPH') |
152 | var c = 0 |
153 | latest(animalNetwork, function (err, _generated) { |
154 | if(err) throw err |
155 | |
156 | generated = _generated |
157 | var total = 0, feeds = 0 |
158 | for(var k in generated) { |
159 | total += generated[k] |
160 | feeds ++ |
161 | } |
162 | |
163 | var time = (Date.now()-start)/1000 |
164 | console.log('generated', total, 'messages in', time, 'at rate:', total/time) |
165 | console.log('over', feeds, 'feeds') |
166 | t.equal(total, N+1+F+1) |
167 | t.equal(feeds, F+1) |
168 | t.end() |
169 | }) |
170 | }) |
171 | }) |
172 | |
173 | tape('read all history streams', function (t) { |
174 | |
175 | var opts = { |
176 | host: 'localhost', port: 45451, |
177 | key: alice.id, |
178 | manifest: animalNetwork.manifest() |
179 | } |
180 | |
181 | var dump = createSbot({ |
182 | temp: 'test-random-animals_dump', |
183 | // port: 45453, host: 'localhost', timeout: 20001, |
184 | keys: bob |
185 | }) |
186 | var live = 0, listeners = 0 |
187 | var since = {} |
188 | |
189 | var h = 0 |
190 | |
191 | pull( |
192 | dump.createLogStream({live: true, keys: false}), |
193 | pull.drain(function (e) { |
194 | 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 | replication: {hops: 3}, |
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 | animalFriends.logging = true |
276 | |
277 | if(!animalFriends.friends) |
278 | throw new Error('missing friends plugin') |
279 | |
280 | animalFriends.publish({ |
281 | type: 'contact', |
282 | contact: animalNetwork.id, |
283 | following: true |
284 | }, function (err, msg) { |
285 | if(err) throw err |
286 | }) |
287 | |
288 | }) |
289 | |
290 | |
291 | tape('shutdown', function (t) { |
292 | animalNetwork.close(true) |
293 | t.end() |
294 | }) |
295 | |
296 | |
297 |
Built with git-ssb-web