Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Avatar for KuCalc : devops.
Download
50664 views
1
###
2
Test suite for PostgreSQL interface and functionality.
3
4
COPYRIGHT : (c) 2017 SageMath, Inc.
5
LICENSE : AGPLv3
6
###
7
8
pgtest = require('./pgtest')
9
db = undefined
10
setup = (cb) -> (pgtest.setup (err) -> db=pgtest.db; cb(err))
11
teardown = pgtest.teardown
12
13
async = require('async')
14
expect = require('expect')
15
16
misc = require('smc-util/misc')
17
{DOMAIN_NAME, SITE_NAME} = require('smc-util/theme')
18
19
describe 'working with accounts: ', ->
20
@timeout(5000)
21
before(setup)
22
after(teardown)
23
it "checks that the account we haven't made yet doesn't already exist", (done) ->
24
db.account_exists
25
email_address: '[email protected]'
26
cb:(err, exists) -> expect(!!exists).toBe(false); done(err)
27
it "tries to get an account that doesn't exist", (done) ->
28
db.get_account
29
email_address:'[email protected]'
30
cb : (err, account) -> expect(err?).toBe(true); done()
31
it "creates a new account", (done) ->
32
db.create_account(first_name:"Sage", last_name:"Salvus", created_by:"1.2.3.4",\
33
email_address:"[email protected]", password_hash:"blah", cb:done)
34
it "checks the newly created account does exist", (done) ->
35
db.account_exists
36
email_address:'[email protected]'
37
cb:(err, exists) -> expect(!!exists).toBe(true); done(err)
38
it "verifies that there is 1 account in the database via a count", (done) ->
39
db.count
40
table : 'accounts'
41
cb : (err, n) -> expect(n).toBe(1); done(err)
42
it "creates a second account", (done) ->
43
db.create_account(first_name:"Mr", last_name:"Smith", created_by:"10.10.1.1",\
44
email_address:"[email protected]", password_hash:"foo", cb:done)
45
it "verifies that there are a total of 2 accounts in the database via the stats table", (done) ->
46
db.get_stats(cb: (err, stats) -> expect(stats.accounts).toBe(2); done(err))
47
it "grabs our second new account by email and checks a name and property", (done) ->
48
db.get_account
49
email_address:'[email protected]'
50
cb:(err, account) ->
51
expect(account.first_name).toBe("Mr")
52
expect(account.password_is_set).toBe(true)
53
done(err)
54
it "computes number of accounts created from 1.2.3.4", (done) ->
55
db.count_accounts_created_by
56
ip_address : '1.2.3.4'
57
age_s : 1000000
58
cb : (err, n) -> expect(n).toBe(1); done(err)
59
it "deletes an account", (done) ->
60
db.get_account
61
email_address:'[email protected]'
62
cb : (err, account) ->
63
db.delete_account
64
account_id : account.account_id
65
cb : done
66
it "checks that account is gone", (done) ->
67
db.account_exists
68
email_address:'[email protected]'
69
cb:(err, exists) -> expect(!!exists).toBe(false); done(err)
70
it "creates an account with no password set", (done) ->
71
db.create_account(first_name:"Simple", last_name:"Sage", created_by:"1.2.3.4",\
72
email_address:"[email protected]", cb:done)
73
it "verifies that the password_is_set field is false", (done) ->
74
db.get_account
75
email_address:'[email protected]'
76
cb:(err, account) -> expect(account.password_is_set).toBe(false); done(err)
77
78
describe 'working with logs: ', ->
79
before(setup)
80
after(teardown)
81
82
it 'creates a log message', (done) ->
83
db.log
84
event : "test"
85
value : "a message"
86
cb : done
87
88
it 'gets contents of the log and checks that the message we made is there', (done) ->
89
db.get_log
90
start : new Date(new Date() - 10000000)
91
end : new Date()
92
event : 'test'
93
cb : (err, log) ->
94
expect(log.length).toBe(1)
95
expect(log[0]).toEqual(event:'test', value:'a message', id:log[0].id, time:log[0].time)
96
done(err)
97
98
it 'checks that there is nothing "old" in the log', (done) ->
99
# no old stuff
100
db.get_log
101
start : new Date(new Date() - 10000000)
102
end : new Date(new Date() - 1000000)
103
cb : (err, log) -> expect(log.length).toBe(0); done(err)
104
105
account_id = '4d29eec4-c126-4f06-b679-9a661fd7bcdf'
106
error = "Your internet connection is unstable/down or #{SITE_NAME} is temporarily not available. Therefore #{SITE_NAME} is not working."
107
event = 'test'
108
it 'logs a client error', (done) ->
109
db.log_client_error
110
event : event
111
error : error
112
account_id : account_id
113
cb : done
114
it 'logs another client error with a different event', (done) ->
115
db.log_client_error
116
event : event + "-other"
117
error : error
118
account_id : account_id
119
cb : done
120
it 'gets the recent error log for only one event and checks that it has only one log entry in it', (done) ->
121
db.get_client_error_log
122
start : new Date(new Date() - 10000000)
123
end : new Date()
124
event : event
125
cb : (err, log) ->
126
expect(log.length).toBe(1)
127
expect(log[0]).toEqual(event:event, error:error, account_id:account_id, id:log[0].id, time:log[0].time)
128
done(err)
129
it 'gets old log entries and makes sure there are none', (done) ->
130
db.get_client_error_log
131
start : new Date(new Date() - 10000000)
132
end : new Date(new Date() - 1000000)
133
event : event
134
cb : (err, log) -> expect(log.length).toBe(0); done(err)
135
136
describe 'testing working with blobs: ', ->
137
beforeEach(setup)
138
afterEach(teardown)
139
{uuidsha1} = require('smc-util-node/misc_node')
140
project_id = misc.uuid()
141
it 'creating a blob and reading it', (done) ->
142
blob = new Buffer("This is a test blob")
143
async.series([
144
(cb) ->
145
db.save_blob(uuid : uuidsha1(blob), blob : blob, project_id : project_id, cb : cb)
146
(cb) ->
147
db.count
148
table : 'blobs'
149
cb : (err, n) ->
150
expect(n).toBe(1)
151
cb(err)
152
(cb) ->
153
db.get_blob
154
uuid : uuidsha1(blob)
155
cb : (err, blob2) ->
156
expect(blob2.equals(blob)).toBe(true)
157
cb(err)
158
], done)
159
160
it 'tries to save a blob with an invalid uuid and gets an error', (done) ->
161
db.save_blob
162
uuid : 'not a uuid'
163
blob : new Buffer("This is a test blob")
164
project_id : project_id
165
cb : (err) ->
166
expect(err).toEqual('uuid is invalid')
167
done()
168
169
it 'save a string blob (with a null byte!), and confirms it works (properly converted to Buffer)', (done) ->
170
async.series([
171
(cb) ->
172
db.save_blob(blob: 'my blob', project_id: project_id, cb: cb)
173
(cb) ->
174
db.get_blob
175
uuid : uuidsha1('my blob')
176
cb : (err, blob2) ->
177
expect(blob2?.toString()).toEqual('my blob')
178
cb(err)
179
], done)
180
181
it 'creating 50 blobs and verifying that 50 are in the table', (done) ->
182
async.series([
183
(cb) ->
184
f = (n, cb) ->
185
blob = new Buffer("x#{n}")
186
db.save_blob(uuid : uuidsha1(blob), blob : blob, project_id : project_id, cb : cb)
187
async.map([0...50], f, cb)
188
(cb) ->
189
db.count
190
table : 'blobs'
191
cb : (err, n) ->
192
expect(n).toBe(50)
193
cb(err)
194
], done)
195
196
it 'creating 5 blobs that expire in 0.01 second and 5 that do not, then wait 0.15s, delete_expired, then verify that the expired ones are gone from the table', (done) ->
197
async.series([
198
(cb) ->
199
f = (n, cb) ->
200
blob = new Buffer("x#{n}")
201
db.save_blob(uuid : uuidsha1(blob), blob : blob, project_id : project_id, cb : cb, ttl:if n<5 then 0.01 else 0)
202
async.map([0...10], f, cb)
203
(cb) ->
204
setTimeout(cb, 150)
205
(cb) ->
206
db.delete_expired(cb:cb)
207
(cb) ->
208
db.count
209
table : 'blobs'
210
cb : (err, n) ->
211
expect(n).toBe(5)
212
cb(err)
213
], done)
214
215
it 'creating a blob that expires in 0.01 seconds, then extending it to never expire; wait, delete, and ensure it is still there', (done) ->
216
blob = "a blob"
217
uuid = uuidsha1(blob)
218
async.series([
219
(cb) ->
220
db.save_blob(uuid : uuid, blob : blob, project_id : project_id, cb : cb, ttl:0.01)
221
(cb) ->
222
db.remove_blob_ttls(uuids:[uuid], cb:cb)
223
(cb) ->
224
setTimeout(cb, 100)
225
(cb) ->
226
db.count
227
table : 'blobs'
228
cb : (err, n) ->
229
expect(n).toBe(1)
230
cb(err)
231
], done)
232
233
describe 'testing the hub servers registration table: ', ->
234
beforeEach(setup)
235
afterEach(teardown)
236
it 'test registering a hub that expires in 0.05 seconds, test is right, then wait 0.1s, delete_expired, then verify done', (done) ->
237
async.series([
238
(cb) ->
239
db.register_hub(host:"smc0", port:5000, clients:17, ttl:0.05, cb:cb)
240
(cb) ->
241
db.get_hub_servers cb:(err, v) ->
242
expect(v.length).toBe(1)
243
expect(v[0]).toEqual({host:"smc0-5000", port:5000, clients:17, expire:v[0].expire})
244
cb(err)
245
(cb) ->
246
setTimeout(cb, 150)
247
(cb) ->
248
db.delete_expired(cb:cb)
249
(cb) ->
250
db.get_hub_servers cb:(err, v) ->
251
expect(v.length).toBe(0)
252
cb(err)
253
], done)
254
255
describe 'testing the server settings table: ', ->
256
before(setup)
257
after(teardown)
258
it 'sets a server setting', (done) ->
259
db.set_server_setting
260
name : 'name'
261
value : "some stuff"
262
cb : done
263
it 'reads that setting back', (done) ->
264
db.get_server_setting
265
name : 'name'
266
cb : (err, value) ->
267
expect(value).toEqual("some stuff")
268
done(err)
269
270
describe 'testing the passport settings table: ', ->
271
before(setup)
272
after(teardown)
273
it 'creates the site_conf passport auth', (done) ->
274
db.set_passport_settings(strategy:'site_conf', conf:{auth:DOMAIN_NAME + '/auth'}, cb: done)
275
it 'verifies that the site_conf passport was created', (done) ->
276
db.get_passport_settings
277
strategy : 'site_conf'
278
cb : (err, value) ->
279
expect(value).toEqual({auth:DOMAIN_NAME + '/auth'})
280
done(err)
281
282
describe 'user enumeration functionality: ', ->
283
before(setup)
284
after(teardown)
285
num = 20
286
it "creates #{num} accounts", (done) ->
287
f = (n, cb) ->
288
db.create_account(first_name:"Sage#{n}", last_name:"Math#{n}", created_by:"1.2.3.4",\
289
email_address:"sage#{n}@sagemath.com", password_hash:"sage#{n}", cb:cb)
290
async.map([0...num], f, done)
291
it "searches for users using the 'sage' query", (done) ->
292
db.user_search
293
query : "sage"
294
limit : num - 2
295
cb : (err, v) ->
296
expect(v.length).toBe(num-2)
297
done(err)
298
it "searches for the user with email [email protected]", (done) ->
299
db.user_search
300
query : "[email protected]"
301
cb : (err, users) ->
302
expect(users.length).toBe(1)
303
n = 0
304
expect(users[0]).toEqual("email_address": "[email protected]", account_id:users[n].account_id, first_name: "Sage#{n}", last_name: "Math#{n}")
305
done(err)
306
it "searches for the non-existent user with email [email protected]", (done) ->
307
db.user_search
308
query : "[email protected]"
309
cb : (err, users) -> expect(users.length).toBe(0); done(err)
310
311
account_id = undefined
312
it "adds another user", (done) ->
313
db.create_account(first_name:"FOO", last_name:"BAR", created_by:"1.2.3.4",\
314
email_address:"[email protected]", password_hash:"sage", cb:(err, x) -> account_id=x; done(err))
315
it "then checks that the new user is found by first name", (done) ->
316
db.user_search
317
query : "FOO"
318
cb : (err, users) -> expect(users.length).toBe(1); done(err)
319
it "then checks that the new user is found by last name", (done) ->
320
db.user_search
321
query : "BAR"
322
cb : (err, users) -> expect(users.length).toBe(1); done(err)
323
it "change that user in place", (done) ->
324
db._query
325
query : "UPDATE accounts"
326
set : {first_name:'VERT', last_name:'RAMP'}
327
where : "account_id = $":account_id
328
cb : done
329
it "then checks that the modified user is found", (done) ->
330
db.user_search
331
query : "VERT"
332
cb : (err, users) -> expect(users.length).toBe(1); done(err)
333
it "but the previous name is not found", (done) ->
334
db.user_search
335
query : "BAR"
336
cb : (err, users) -> expect(users.length).toBe(0); done(err)
337
338
describe 'banning of users: ', ->
339
before(setup)
340
after(teardown)
341
account_id = undefined
342
it 'creates an account', (done) ->
343
db.create_account(first_name:"Sage", last_name:"Math", created_by:"1.2.3.4",\
344
email_address:"[email protected]", password_hash:"blah", cb:(err, x) => account_id=x; done(err))
345
it 'checks by account_id that the user we just created is not banned', (done) ->
346
db.is_banned_user(account_id:account_id, cb:(err,x)=>expect(x).toBe(false); done(err))
347
it 'checks by email that user is not banned', (done) ->
348
db.is_banned_user(email_address:"[email protected]", cb:(err,x)=>expect(x).toBe(false); done(err))
349
it 'verifies that a user that does not exist is not banned', (done) ->
350
db.is_banned_user(email_address:"[email protected]", cb:(err,x)=>expect(x).toBe(false); done(err))
351
it 'bans the user we created', (done) ->
352
db.ban_user(account_id:account_id, cb:done)
353
it 'checks they are banned by account_id', (done) ->
354
db.is_banned_user(account_id:account_id, cb:(err,x)=>expect(x).toBe(true); done(err))
355
it 'checks they are banned by email address', (done) ->
356
db.is_banned_user(email_address:"[email protected]", cb:(err,x)=>expect(x).toBe(true); done(err))
357
it 'unbans our banned user', (done) ->
358
db.unban_user(account_id:account_id, cb:done)
359
it 'checks that the user we just unbanned is unbanned', (done) ->
360
db.is_banned_user(account_id:account_id, cb:(err,x)=>expect(x).toBe(false); done(err))
361
it 'bans our user by email address instead', (done) ->
362
db.ban_user(email_address:"[email protected]", cb:done)
363
it 'then checks that banning by email address worked', (done) ->
364
db.is_banned_user(account_id:account_id, cb:(err,x)=>expect(x).toBe(true); done(err))
365
366
describe 'testing the passport table: ', ->
367
before(setup)
368
after(teardown)
369
account_id = undefined
370
it 'creates an account', (done) ->
371
db.create_account(first_name:"Sage", last_name:"Math", created_by:"1.2.3.4",\
372
email_address:"[email protected]", password_hash:"blah", cb:(err, x) => account_id=x; done(err))
373
it 'creates a passport', (done) ->
374
db.create_passport
375
account_id : account_id
376
strategy : 'google'
377
id : '929304823048'
378
profile : {email_address:"[email protected]", avatar:'James Cameron'}
379
cb : done
380
it 'checks the passport we just created exists', (done) ->
381
db.passport_exists
382
strategy : 'google'
383
id : '929304823048'
384
cb : (err, x) ->
385
expect(x).toBe(account_id)
386
done(err)
387
it 'check that a non-existent passport does not exist', (done) ->
388
db.passport_exists
389
strategy : 'google'
390
id : 'FAKE'
391
cb : (err, x) ->
392
expect(x).toBe(undefined)
393
done(err)
394
it 'check that a passport we created above exists directly via checking the accounts entry', (done) ->
395
db.get_account
396
account_id : account_id
397
columns : ['passports']
398
cb : (err, x) ->
399
expect(x.passports).toEqual( 'google-929304823048': { avatar: 'James Cameron', email_address: '[email protected]' })
400
done(err)
401
it 'deletes the passport we made above', (done) ->
402
db.delete_passport
403
account_id : account_id
404
strategy : 'google'
405
id : '929304823048'
406
cb : done
407
it 'verifies the passport is really gone', (done) ->
408
db.passport_exists
409
strategy : 'google'
410
id : '929304823048'
411
cb : (err, x) ->
412
expect(x).toBe(undefined)
413
done(err)
414
it 'check the passport is also gone from the accounts table', (done) ->
415
db.get_account
416
account_id : account_id
417
columns : ['passports']
418
cb : (err, x) ->
419
expect(misc.keys(x.passports).length).toEqual(0)
420
done(err)
421
it 'create two passports and verifies that both exist', (done) ->
422
async.series([
423
(cb) ->
424
db.create_passport
425
account_id : account_id
426
strategy : 'google'
427
id : '929304823048'
428
profile : {email_address:"[email protected]", avatar:'James Cameron'}
429
cb : cb
430
(cb) ->
431
db.create_passport
432
account_id : account_id
433
strategy : 'facebook'
434
id : '12346'
435
profile : {email_address:"[email protected]", avatar:'Zuck'}
436
cb : cb
437
(cb) ->
438
db.get_account
439
account_id : account_id
440
columns : ['passports']
441
cb : (err, x) ->
442
expect(misc.keys(x.passports).length).toEqual(2)
443
cb(err)
444
], done)
445
446
describe 'testing file use notifications table: ', ->
447
before(setup)
448
after(teardown)
449
account_id = undefined
450
project_id = undefined
451
path0 = "test_file"
452
it 'creates an account', (done) ->
453
db.create_account(first_name:"Sage", last_name:"Math", created_by:"1.2.3.4",\
454
email_address:"[email protected]", password_hash:"blah", cb:(err, x) => account_id=x; done(err))
455
it 'creates a project', (done) ->
456
db.create_project(account_id:account_id, title:"Test project", description:"The description",\
457
cb:(err, x) => project_id=x; done(err))
458
it "record editing of file '#{path0}'", (done) ->
459
db.record_file_use(project_id: project_id, path:path0, account_id:account_id, action:"edit", cb:done)
460
it "get activity for project and '#{path0}'", (done) ->
461
db.get_file_use(project_id: project_id, path : path0, max_age_s : 1000, cb:(err, x)->
462
expect(x.project_id).toBe(project_id)
463
expect(x.path).toBe(path0)
464
expect(misc.keys(x.users)).toEqual([account_id])
465
expect(misc.keys(x.users[account_id])).toEqual(['edit'])
466
done(err)
467
)
468
it "get activity for the project and ensure there was is instance of activity", (done) ->
469
db.get_file_use(project_id: project_id, max_age_s : 1000, cb:(err, x)-> expect(x.length).toBe(1); done(err))
470
471
path1 = "another_file"
472
project_id1 = undefined
473
it 'creates another project', (done) ->
474
db.create_project(account_id:account_id, title:"Test project 2", description:"The description 2",\
475
cb:(err, x) => project_id1=x; done(err))
476
477
it "tests recording activity on another file '#{path1}'", (done) ->
478
db.record_file_use(project_id: project_id1, path:path1, account_id:account_id, action:"edit", cb:done)
479
480
it "gets activity only for the second project and checks there is only one entry", (done) ->
481
db.get_file_use(project_id: project_id1, max_age_s : 1000, cb:(err, x)-> expect(x.length).toBe(1); done(err))
482
483
it "gets activity for both projects and checks there are two entries", (done) ->
484
db.get_file_use(project_ids:[project_id, project_id1], max_age_s : 1000, cb:(err, x)-> expect(x.length).toBe(2); done(err))
485
486
it "gets all info about a project", (done) ->
487
db.get_project
488
project_id : project_id
489
cb : (err, info) ->
490
expect(info?.title).toEqual('Test project')
491
expect(info?.project_id).toEqual(project_id)
492
done(err)
493
494
account_id1 = undefined
495
path2 = "a_third_file"
496
it 'creates another account', (done) ->
497
db.create_account(first_name:"Sage1", last_name:"Math1", created_by:"1.2.3.4",\
498
email_address:"[email protected]", password_hash:"blah1", cb:(err, x) => account_id1=x; done(err))
499
it "records activity by new user on '#{path0}", (done) ->
500
db.record_file_use(project_id: project_id, path:path0, account_id:account_id1, action:"edit", cb:done)
501
it "checks that there is still one activity entry for first project", (done) ->
502
db.get_file_use(project_id: project_id, max_age_s : 1000, cb:(err, x)-> expect(x.length).toBe(1); done(err))
503
it "checks two users are listed as editors on '#{path0}'", (done) ->
504
db.get_file_use(project_id: project_id, path: path0, max_age_s : 1000, cb:(err, x)-> expect(misc.keys(x.users).length).toBe(2); done(err))
505
it "records activity by new user on '#{path2}", (done) ->
506
db.record_file_use(project_id: project_id, path:path2, account_id:account_id1, action:"edit", cb:done)
507
it "checks that there are two activity entries now for first project", (done) ->
508
db.get_file_use(project_id: project_id, max_age_s : 1000, cb:(err, x)-> expect(x.length).toBe(2); done(err))
509
it "gets activity for both projects and checks there are now three entries", (done) ->
510
db.get_file_use(project_ids:[project_id, project_id1], max_age_s : 1000, cb:(err, x)-> expect(x.length).toBe(3); done(err))
511
512
it "verifies that max_age_s filter works", (done) ->
513
f = () ->
514
db.get_file_use(project_ids:[project_id, project_id1], max_age_s:0.05, cb:(err, x)-> expect(x.length).toBe(0); done(err))
515
setTimeout(f,100)
516
517
it "records edit action again on a file by a user and verifies that this changes the last_edited field", (done) ->
518
last_edited = undefined
519
async.series([
520
(cb) ->
521
db.get_file_use(project_id:project_id, path: path0, max_age_s:1000, cb:(err, x)-> last_edited=x.last_edited; cb(err))
522
(cb) ->
523
db.record_file_use(project_id:project_id, path:path0, account_id:account_id, action:"edit", cb:cb)
524
(cb) ->
525
db.get_file_use(project_id:project_id, path: path0, max_age_s:1000, cb:(err, x)-> expect(last_edited).toNotBe(x.last_edited); cb(err))
526
], done)
527
528
it "records seen action on a file by a user and verifies that this does not change the last_edited field and adds seen info", (done) ->
529
async.series([
530
(cb) ->
531
db.record_file_use(project_id:project_id, path:path0, account_id:account_id, action:"seen", cb:cb)
532
(cb) ->
533
db.get_file_use(project_id:project_id, path: path0, max_age_s:1000, cb:(err, x)->
534
expect(x.users[account_id].seen?).toBe(true)
535
expect(x.users[account_id].read?).toBe(false)
536
cb(err))
537
], done)
538
539
540
describe 'doing a "naked update"', ->
541
it 'is an error', (done) ->
542
db._query
543
query : "UPDATE accounts SET first_name='William'"
544
cb : (err) ->
545
expect(err).toEqual("ERROR -- Dangerous UPDATE or DELETE without a WHERE, TRIGGER, or INSERT: query='UPDATE accounts SET first_name='William''")
546
done()
547
548
549