Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Avatar for KuCalc : devops.
Download
50671 views
1
###
2
TESTING of syncstring related eval user query functionality
3
4
COPYRIGHT : (c) 2017 SageMath, Inc.
5
LICENSE : AGPLv3
6
###
7
8
async = require('async')
9
expect = require('expect')
10
11
pgtest = require('./pgtest')
12
db = undefined
13
setup = (cb) -> (pgtest.setup (err) -> db=pgtest.db; cb(err))
14
teardown = pgtest.teardown
15
16
{create_accounts, create_projects, changefeed_series} = pgtest
17
misc = require('smc-util/misc')
18
19
describe 'use of eval_inputs table --', ->
20
before(setup)
21
after(teardown)
22
23
accounts = projects = string_id = undefined
24
path = 'a.txt'
25
it 'creates 3 accounts', (done) ->
26
create_accounts 3, (err, x) -> accounts=x; done(err)
27
it 'creates 2 projects', (done) ->
28
create_projects 2, accounts[0], (err, x) -> projects=x; done(err)
29
30
t0 = new Date()
31
input =
32
program : 'sage'
33
input :
34
code : '2^a'
35
data : {a:3}
36
preparse : true
37
event : 'execute_code'
38
output_uuid : misc.uuid()
39
id : misc.uuid()
40
41
it 'creates a valid syncstring', (done) ->
42
db.user_query
43
account_id : accounts[0]
44
query : {syncstrings:{project_id:projects[0], path:'a.sagews', users:accounts}}
45
cb : done
46
47
it 'gets the string_id', (done) ->
48
db.user_query
49
account_id : accounts[0]
50
query : {syncstrings:{project_id:projects[0], path:'a.sagews', string_id:null}}
51
cb : (err, result) ->
52
string_id = result?.syncstrings.string_id
53
done(err)
54
55
it 'verifies anonymous set queries are not allowed', (done) ->
56
db.user_query
57
query : {eval_inputs:{string_id:string_id, time:t0, user_id:0, input:input}}
58
cb : (err) ->
59
expect(err).toEqual("no anonymous set queries")
60
done()
61
62
it 'verifies anonymous get queries are not allowed', (done) ->
63
db.user_query
64
query : {eval_inputs:[{string_id:string_id, time:null, user_id:null, input:null}]}
65
cb : (err) ->
66
expect(err).toEqual("anonymous get queries not allowed for table 'eval_inputs'")
67
done()
68
69
it 'verifies set query by user not on syncstring is not allowed', (done) ->
70
db.user_query
71
account_id : accounts[2]
72
query : {eval_inputs:{string_id:string_id, time:t0, user_id:0, input:input}}
73
cb : (err) ->
74
expect(err).toEqual("user must be an admin")
75
done()
76
77
it 'verifies get query by user not on project not allowed', (done) ->
78
db.user_query
79
account_id : accounts[2]
80
query : {eval_inputs:[{string_id:string_id, time:null, user_id:null, input:null}]}
81
cb : (err) ->
82
expect(err).toEqual("user must be an admin")
83
done()
84
85
it 'make that user an admin', (done) ->
86
db.make_user_admin(account_id:accounts[2], cb:done)
87
88
test_write_and_read = (account_id, project_id, cb) ->
89
db.clear_cache()
90
async.series([
91
(cb) ->
92
# deletes records
93
db._query
94
query : "DELETE FROM eval_inputs"
95
safety_check : false
96
cb : cb
97
(cb) ->
98
db.user_query
99
account_id : account_id
100
project_id : project_id
101
query : {eval_inputs:{string_id:string_id, time:t0, user_id:0, input:input}}
102
cb : cb
103
(cb) ->
104
db.user_query
105
account_id : account_id
106
project_id : project_id
107
query : {eval_inputs:[{string_id:string_id, time:null, user_id:null, input:null}]}
108
cb : (err, x) ->
109
expect(x).toEqual({ eval_inputs: [ { input: input, string_id: string_id, time: t0, user_id: 0 } ] })
110
cb(err)
111
], cb)
112
113
it 'verifies set/get by admin user', (done) ->
114
test_write_and_read(accounts[2], undefined, done)
115
116
it 'verifies set/get FAILS by user who is listed on syncstring, but is actually not on project', (done) ->
117
test_write_and_read accounts[1], undefined, (err) ->
118
expect(err).toEqual('user must be an admin')
119
done()
120
121
it 'adds other user to project', (done) ->
122
db.add_user_to_project(account_id:accounts[1], project_id:projects[0], cb:done)
123
124
it 'verifies set/get succeeds by other user who is listed on syncstring and is now on project', (done) ->
125
test_write_and_read(accounts[1], undefined, done)
126
127
it 'verifies set/get by other project fails', (done) ->
128
test_write_and_read undefined, projects[1], (err) ->
129
expect(err).toEqual('project not allowed to write to syncstring in different project')
130
done()
131
132
# one that succeeds should be done last, since this is used below.
133
it 'verifies set/get by user of syncstring', (done) ->
134
test_write_and_read(accounts[0], undefined, done)
135
136
t1 = misc.hours_ago(5)
137
it 'writes an old eval_inputs', (done) ->
138
db.user_query
139
account_id : accounts[0]
140
query : {eval_inputs:{string_id:string_id, time:t1, user_id:0, input:input}}
141
cb : done
142
143
it 'queries for eval_inputs newer than some time', (done) ->
144
db.user_query
145
account_id : accounts[0]
146
query : {eval_inputs:[{string_id:string_id, time:{'>=':misc.hours_ago(4)}, user_id:null, input:null}]}
147
cb : (err, x) ->
148
expect(x).toEqual({ eval_inputs: [ { input: input, string_id: string_id, time: t0, user_id: 0 } ] })
149
done(err)
150
151
it 'queries for eval_inputs older than some time', (done) ->
152
db.user_query
153
account_id : accounts[0]
154
query : {eval_inputs:[{string_id:string_id, time:{'<=':misc.hours_ago(4)}, user_id:null, input:null}]}
155
cb : (err, x) ->
156
expect(x).toEqual({ eval_inputs: [ { input: input, string_id: string_id, time: t1, user_id: 0 } ] })
157
done(err)
158
159
it 'checks that string_id must be given', (done) ->
160
db.user_query
161
account_id : accounts[0]
162
query : {eval_inputs:[{string_id:null, time:null, user_id:null, input:null}]}
163
cb : (err, x) ->
164
expect(err).toEqual("string_id (='null') must be a string of length 40")
165
done()
166
167
it 'verifies that user_id must be nonnegative', (done) ->
168
db.user_query
169
account_id : accounts[0]
170
query : {eval_inputs:{string_id:string_id, time:t1, user_id:-1, input:input}}
171
cb : (err) ->
172
expect(err).toContain('new row for relation "eval_inputs" violates check constraint')
173
done()
174
175
it 'inserts an ugly-formatted date, which works', (done) ->
176
db.user_query
177
account_id : accounts[0]
178
query : {eval_inputs:{string_id:string_id, time:'Wed Feb 01 2017 19:04:10 GMT-0600 (Central Standard Time)1', user_id:0, input:input}}
179
cb : (done)
180
181
it 'inserts an horribly-formatted non-date, which does NOT work', (done) ->
182
db.user_query
183
account_id : accounts[0]
184
query : {eval_inputs:{string_id:string_id, time:'laksdjfasdf', user_id:0, input:input}}
185
cb : (err) ->
186
expect(err).toContain('invalid input syntax for type timestamp')
187
done()
188
189
it 'tests uses of eval_inputs changefeed', (done) ->
190
changefeed_id = misc.uuid()
191
t2 = new Date()
192
db.user_query
193
project_id : projects[0]
194
query : {eval_inputs:[{string_id:string_id, time:{'>=':misc.hours_ago(4)}, user_id:null, input:null}]}
195
changes : changefeed_id
196
cb : changefeed_series([
197
(x, cb) ->
198
expect(x.eval_inputs.length).toEqual(1)
199
200
# write old input -- no update
201
db.user_query
202
account_id : accounts[0]
203
query : {eval_inputs:{string_id:string_id, time:misc.hours_ago(10), user_id:0, input:input}}
204
cb : (err) ->
205
if err
206
cb(err); return
207
# write new input, which triggers a response
208
db.user_query
209
account_id : accounts[0]
210
query : {eval_inputs:{string_id:string_id, time:t2, user_id:0, input:input}}
211
cb : cb
212
(x, cb) ->
213
expect(x).toEqual({action:'insert', new_val:{string_id:string_id, time:t2, user_id:0, input:input}})
214
# modify existing input
215
db.user_query
216
account_id : accounts[0] # query has deep merge semantics by default.
217
query : {eval_inputs:{string_id:string_id, time:t2, user_id:0, input:{foo:'bar'}}}
218
cb : cb
219
(x, cb) ->
220
expect(x).toEqual({action:'update', new_val:{string_id:string_id, time:t2, user_id:0, input:misc.merge({foo:'bar'},input)}})
221
222
db.user_query_cancel_changefeed(id:changefeed_id, cb:cb)
223
(x, cb) ->
224
expect(x).toEqual({action:'close'})
225
226
cb()
227
], done)
228
229
230
# NOTE: this is very similar to eval_inputs above.
231
describe 'use of eval_outputs table --', ->
232
before(setup)
233
after(teardown)
234
235
accounts = projects = string_id = undefined
236
path = 'a.txt'
237
it 'creates 3 accounts', (done) ->
238
create_accounts 3, (err, x) -> accounts=x; done(err)
239
it 'creates 2 projects', (done) ->
240
create_projects 2, accounts[0], (err, x) -> projects=x; done(err)
241
242
t0 = new Date()
243
output = {stdout:"hello world", done:true}
244
245
it 'creates a valid syncstring', (done) ->
246
db.user_query
247
account_id : accounts[0]
248
query : {syncstrings:{project_id:projects[0], path:'a.sagews', users:accounts}}
249
cb : done
250
251
it 'gets the string_id', (done) ->
252
db.user_query
253
account_id : accounts[0]
254
query : {syncstrings:{project_id:projects[0], path:'a.sagews', string_id:null}}
255
cb : (err, result) ->
256
string_id = result?.syncstrings.string_id
257
done(err)
258
259
it 'verifies anonymous set queries are not allowed', (done) ->
260
db.user_query
261
query : {eval_outputs:{string_id:string_id, time:t0, number:0, output:output}}
262
cb : (err) ->
263
expect(err).toEqual("no anonymous set queries")
264
done()
265
266
it 'verifies anonymous get queries are not allowed', (done) ->
267
db.user_query
268
query : {eval_outputs:[{string_id:string_id, time:null, number:null, output:null}]}
269
cb : (err) ->
270
expect(err).toEqual("anonymous get queries not allowed for table 'eval_outputs'")
271
done()
272
273
it 'verifies set query by user not on syncstring is not allowed', (done) ->
274
db.user_query
275
account_id : accounts[2]
276
query : {eval_outputs:{string_id:string_id, time:t0, number:0, output:output}}
277
cb : (err) ->
278
expect(err).toEqual("user must be an admin")
279
done()
280
281
it 'verifies get query by user not on project not allowed', (done) ->
282
db.user_query
283
account_id : accounts[2]
284
query : {eval_outputs:[{string_id:string_id, time:null, number:null, output:null}]}
285
cb : (err) ->
286
expect(err).toEqual("user must be an admin")
287
done()
288
289
it 'make that user an admin', (done) ->
290
db.make_user_admin(account_id:accounts[2], cb:done)
291
292
test_write_and_read = (account_id, project_id, cb) ->
293
db.clear_cache()
294
async.series([
295
(cb) ->
296
# deletes records
297
db._query
298
query : "DELETE FROM eval_outputs"
299
safety_check : false
300
cb : cb
301
(cb) ->
302
db.user_query
303
account_id : account_id
304
project_id : project_id
305
query : {eval_outputs:{string_id:string_id, time:t0, number:0, output:output}}
306
cb : cb
307
(cb) ->
308
db.user_query
309
account_id : account_id
310
project_id : project_id
311
query : {eval_outputs:[{string_id:string_id, time:null, number:null, output:null}]}
312
cb : (err, x) ->
313
expect(x).toEqual({ eval_outputs: [ { output: output, string_id: string_id, time: t0, number: 0 } ] })
314
cb(err)
315
], cb)
316
317
it 'verifies set/get by admin user', (done) ->
318
test_write_and_read(accounts[2], undefined, done)
319
320
it 'verifies set/get FAILS by user who is listed on syncstring, but is actually not on project', (done) ->
321
test_write_and_read accounts[1], undefined, (err) ->
322
expect(err).toEqual('user must be an admin')
323
done()
324
325
it 'adds other user to project', (done) ->
326
db.add_user_to_project(account_id:accounts[1], project_id:projects[0], cb:done)
327
328
it 'verifies set/get succeeds by other user who is listed on syncstring and is now on project', (done) ->
329
test_write_and_read(accounts[1], undefined, done)
330
331
it 'verifies set/get by other project fails', (done) ->
332
test_write_and_read undefined, projects[1], (err) ->
333
expect(err).toEqual('project not allowed to write to syncstring in different project')
334
done()
335
336
# one that succeeds should be done last, since this is used below.
337
it 'verifies set/get by user of syncstring', (done) ->
338
test_write_and_read(accounts[0], undefined, done)
339
340
t1 = misc.hours_ago(5)
341
it 'writes an old eval_outputs', (done) ->
342
db.user_query
343
account_id : accounts[0]
344
query : {eval_outputs:{string_id:string_id, time:t1, number:0, output:output}}
345
cb : done
346
347
it 'queries for eval_outputs newer than some time', (done) ->
348
db.user_query
349
account_id : accounts[0]
350
query : {eval_outputs:[{string_id:string_id, time:{'>=':misc.hours_ago(4)}, number:null, output:null}]}
351
cb : (err, x) ->
352
expect(x).toEqual({ eval_outputs: [ { output: output, string_id: string_id, time: t0, number: 0 } ] })
353
done(err)
354
355
it 'queries for eval_outputs older than some time', (done) ->
356
db.user_query
357
account_id : accounts[0]
358
query : {eval_outputs:[{string_id:string_id, time:{'<=':misc.hours_ago(4)}, number:null, output:null}]}
359
cb : (err, x) ->
360
expect(x).toEqual({ eval_outputs: [ { output: output, string_id: string_id, time: t1, number: 0 } ] })
361
done(err)
362
363
it 'checks that string_id must be given', (done) ->
364
db.user_query
365
account_id : accounts[0]
366
query : {eval_outputs:[{string_id:null, time:null, number:null, output:null}]}
367
cb : (err, x) ->
368
expect(err).toEqual("string_id (='null') must be a string of length 40")
369
done()
370
371
it 'verifies that number must be nonnegative', (done) ->
372
db.user_query
373
account_id : accounts[0]
374
query : {eval_outputs:{string_id:string_id, time:t1, number:-1, output:output}}
375
cb : (err) ->
376
expect(err).toContain('new row for relation "eval_outputs" violates check constraint')
377
done()
378
379
it 'tests uses of eval_outputs changefeed', (done) ->
380
changefeed_id = misc.uuid()
381
t2 = new Date()
382
db.user_query
383
account_id : accounts[0]
384
query : {eval_outputs:[{string_id:string_id, time:{'>=':misc.hours_ago(4)}, number:null, output:null}]}
385
changes : changefeed_id
386
cb : changefeed_series([
387
(x, cb) ->
388
expect(x.eval_outputs.length).toEqual(1)
389
390
# write old output -- no update
391
db.user_query
392
project_id : projects[0]
393
query : {eval_outputs:{string_id:string_id, time:misc.hours_ago(10), number:0, output:output}}
394
cb : (err) ->
395
if err
396
cb(err); return
397
# write new output, which triggers a response
398
db.user_query
399
project_id : projects[0]
400
query : {eval_outputs:{string_id:string_id, time:t2, number:0, output:output}}
401
cb : cb
402
(x, cb) ->
403
expect(x).toEqual({action:'insert', new_val:{string_id:string_id, time:t2, number:0, output:output}})
404
405
# modify existing output
406
db.user_query
407
project_id : projects[0] # query has deep merge semantics by default.
408
query : {eval_outputs:{string_id:string_id, time:t2, number:0, output:{foo:'bar'}}}
409
cb : cb
410
(x, cb) ->
411
expect(x).toEqual({action:'update', new_val:{string_id:string_id, time:t2, number:0, output:misc.merge({foo:'bar'},output)}})
412
413
db.user_query_cancel_changefeed(id:changefeed_id, cb:cb)
414
(x, cb) ->
415
expect(x).toEqual({action:'close'})
416
417
cb()
418
], done)
419
420