Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Avatar for KuCalc : devops.
Download
50640 views
1
###############################################################################
2
#
3
# CoCalc: Collaborative web-based calculation
4
# Copyright (C) 2017, Sagemath Inc.
5
# AGPLv3
6
#
7
###############################################################################
8
require('coffee-cache')
9
10
{db_doc, from_str, from_obj} = require('../db-doc')
11
misc = require('../misc')
12
13
expect = require('expect')
14
15
describe "test a simple db doc with one record -- ", ->
16
db = undefined
17
18
it "makes the db", ->
19
db = db_doc(primary_keys: ['id'])
20
expect(db.size).toBe(0)
21
22
it "adds one record", ->
23
db = db.set(name:"Sage", id:"123")
24
expect(db.size).toBe(1)
25
expect(db.get().toJS()).toEqual([{name:'Sage', id:'123'}])
26
27
it "modifies that record", ->
28
db = db.set
29
name : "SageMath"
30
id : "123"
31
expect(db.size).toBe(1)
32
expect(db.get().toJS()).toEqual([{name:'SageMath', id:'123'}])
33
34
it "deletes that record", ->
35
db = db.delete(id:"123")
36
expect(db.size).toBe(0)
37
expect(db.get().toJS()).toEqual([])
38
39
40
# Using many records is partly a test that I didn't make things stupidly
41
# inefficient via some change.
42
numdocs = 1000
43
describe "test a db doc with #{numdocs} records and one indexed column -- ", ->
44
db = undefined
45
it "makes the db", ->
46
db = db_doc(primary_keys: ['id'])
47
expect(db.size).toBe(0)
48
49
it "adds #{numdocs} documents to db", ->
50
#t0 = new Date()
51
for i in [0...numdocs]
52
db = db.set(name: "Sage #{i}", id: i)
53
#console.log(new Date() - t0)
54
expect(db.size).toBe(numdocs)
55
56
it "modifies a document", ->
57
expect(db.get_one(id:500).toJS()).toEqual({name:'Sage 500', id:500})
58
db = db.set(name : "SageXYZ", id : 500)
59
expect(db.get_one(id:500).toJS()).toEqual({name:'SageXYZ', id:500})
60
61
it "deletes a document", ->
62
db = db.delete(id:500)
63
expect(db.size).toEqual(numdocs-1)
64
expect(db.get_one(id:500)).toEqual(undefined)
65
66
it "deletes all documents", ->
67
db = db.delete()
68
expect(db.size).toEqual(0)
69
70
71
describe "test a db with two indexed cols -- ", ->
72
db = undefined
73
times = [misc.minutes_ago(3), misc.minutes_ago(2), misc.minutes_ago(1)]
74
75
it "makes db with two indexed cols", ->
76
db = db_doc(primary_keys: ['time', 'user'])
77
expect(db.size).toBe(0)
78
79
it 'adds an record', ->
80
db = db.set
81
mesg : "what is going on?"
82
time : times[0]
83
user : 0
84
expect(db.size).toBe(1)
85
expect(db.get_one().toJS()).toEqual({mesg:"what is going on?", time:times[0], user:0})
86
87
it 'updates that record based on time indexed field', ->
88
db = db.set
89
mesg : 'what is going on now?'
90
time : times[0]
91
expect(db.size).toBe(1)
92
expect(db.get_one().toJS()).toEqual({mesg:"what is going on now?", time:times[0], user:0})
93
94
it 'updates that record based on user indexed field', ->
95
db = db.set
96
mesg : 'what is going on then?'
97
user : 0
98
expect(db.size).toBe(1)
99
expect(db.get_one().toJS()).toEqual({mesg:"what is going on then?", time:times[0], user:0})
100
101
it 'adds more records', ->
102
db = db.set
103
mesg : "nothing much"
104
time : times[1]
105
user : 1
106
db = db.set
107
mesg : "nothing much here either"
108
time : times[2]
109
user : 0
110
expect(db.size).toBe(3)
111
expect(db.get().size).toBe(3)
112
113
it 'queries for records by time', ->
114
expect(db.get({time:times[0]}).size).toBe(1)
115
expect(db.get({time:times[1]}).size).toBe(1)
116
expect(db.get({time:times[2]}).size).toBe(1)
117
expect(db.get({time:new Date()}).size).toBe(0)
118
119
it 'queries for records by user', ->
120
expect(db.get({user:0}).size).toBe(2)
121
expect(db.get({user:1}).size).toBe(1)
122
expect(db.get({user:2}).size).toBe(0)
123
124
it 'modified record based on time', ->
125
db = db.set
126
mesg : "nothing much (!)"
127
time : times[1]
128
expect(db.get_one(time:times[1]).toJS()).toEqual({mesg:'nothing much (!)', time:times[1], user:1})
129
130
131
describe "test a db with index on complicated objects -- ", ->
132
db = undefined
133
times = [misc.minutes_ago(3), misc.minutes_ago(2), misc.minutes_ago(1)]
134
it "makes db with two indexed cols", ->
135
db = db_doc(primary_keys: ['field1', 'field 2'])
136
expect(db.size).toBe(0)
137
138
it "creates two records", ->
139
db = db.set
140
data : "foo bar"
141
field1 : {time:times[0]}
142
'field 2': {foo:'bar', a:5, z:[times]}
143
144
db = db.set
145
data : "foo bar 2"
146
field1 : {time:times[1]}
147
'field 2': {foo:'bar', a:5, z:[times]}
148
149
expect(db.size).toBe(2)
150
151
it "selects each record", ->
152
x = db.get_one(field1:{time:times[1]}).toJS()
153
expect(x).toEqual(data:"foo bar 2", field1:{time:times[1]}, 'field 2':{foo:'bar', a:5, z:[times]})
154
155
x = db.get_one(field1:{time:times[0]}).toJS()
156
expect(x).toEqual(data:"foo bar", field1:{time:times[0]}, 'field 2':{foo:'bar', a:5, z:[times]})
157
158
159
describe 'test error handling of non-indexed cols -- ', ->
160
db = undefined
161
162
it "makes the db", ->
163
db = db_doc(primary_keys: ['id'])
164
expect(db.size).toBe(0)
165
166
it 'try to use a non-indexed column', ->
167
try
168
db.set
169
name : 'foo'
170
stuff : 'bar'
171
catch e
172
expect("#{e}").toEqual("Error: field \'stuff\' must be indexed")
173
174
it "tests that you can't use set on an indexed col ", ->
175
176
177
describe "create multiple db's at once -- ", ->
178
db1 = db2 = undefined
179
180
it "makes the db's", ->
181
db1 = db_doc(primary_keys: ['id'])
182
expect(db1.size).toBe(0)
183
db2 = db_doc(primary_keys: ['name'])
184
expect(db2.size).toBe(0)
185
186
it "add some records to each", ->
187
db1 = db1.set(id:123, name:'sagemath')
188
expect(db1.size).toBe(1)
189
expect(db2.size).toBe(0)
190
db2 = db2.set(id:5077, name:'sagemath')
191
expect(db1.size).toBe(1)
192
expect(db2.size).toBe(1)
193
194
it 'modify each', ->
195
db1 = db1.set(id:123, name:'sage')
196
db2 = db2.set(id:389, name:'sagemath')
197
expect(db1.size).toBe(1)
198
expect(db2.size).toBe(1)
199
expect(db1.get_one().toJS()).toEqual(id:123, name:'sage')
200
expect(db2.get_one().toJS()).toEqual(id:389, name:'sagemath')
201
202
it 'delete from each', ->
203
db1 = db1.delete()
204
expect(db1.size).toBe(0)
205
expect(db2.size).toBe(1)
206
db2 = db2.delete()
207
expect(db1.size).toBe(0)
208
expect(db2.size).toBe(0)
209
210
211
describe 'ensure first entry only is updated -- ', ->
212
213
db = undefined
214
215
it "makes the db", ->
216
db = db_doc(primary_keys: ['id', 'group'])
217
expect(db.size).toBe(0)
218
219
it "adds records", ->
220
db = db.set(name:"Sage0", id:"389", group:'user')
221
db = db.set(name:"Sage1", id:"123", group:'admin')
222
db = db.set(name:"Sage2", id:"389", group:'admin')
223
db = db.set(name:"Sage3", id:"5077", group:'admin')
224
expect(db.size).toBe(4)
225
expect(db.get(group:'admin').size).toBe(3)
226
expect(db.get(id:'389').size).toBe(2)
227
228
it "modifies a specifically selected record", ->
229
db = db.set(score:5, name:'Sage2+', id:'389', group:'admin')
230
expect(db.get_one(id:'389', group:'admin').toJS()).toEqual({id:'389', group:'admin', name:'Sage2+', score:5})
231
232
describe 'test conversion from and to obj -- ', ->
233
db = undefined
234
time = new Date()
235
236
it "makes the db", ->
237
db = db_doc(primary_keys: ['id', 'group'])
238
expect(db.size).toBe(0)
239
240
it "adds records", ->
241
db = db.set(name:"Sage0", active:time, id:"389", group:'user')
242
db = db.set(name:"Sage1", id:"123", group:'admin')
243
db = db.set(name:"Sage2", id:"389", group:'admin')
244
db = db.set(name:"Sage3", id:"5077", group:'admin')
245
246
it 'convert to obj', ->
247
obj = db.to_obj()
248
expect(obj).toEqual([{name:"Sage0", active:time, id:"389", group:'user'}, {name:"Sage1", id:"123", group:'admin'}, {name:"Sage2", id:"389", group:'admin'}, {name:"Sage3", id:"5077", group:'admin'}])
249
250
it 'delete two records, then convert to obj', ->
251
n = db.size
252
db = db.delete(id:'389')
253
expect(n - db.size).toEqual(2)
254
obj = db.to_obj()
255
expect(obj).toEqual([{name:"Sage1", id:"123", group:'admin'}, {name:"Sage3", id:"5077", group:'admin'}])
256
257
it 'convert from obj', ->
258
db2 = from_obj(obj:db.to_obj(), primary_keys: ['id', 'group'])
259
expect(db2.equals(db)).toBe(true)
260
261
262
describe 'test conversion from and to strings -- ', ->
263
db = undefined
264
time = new Date()
265
266
it "makes the db", ->
267
db = db_doc(primary_keys: ['id', 'group'])
268
expect(db.size).toBe(0)
269
270
it "adds records", ->
271
db = db.set(name:"Sage0", active:time, id:"389", group:'user')
272
db = db.set(name:"Sage1", id:"123", group:'admin')
273
db = db.set(name:"Sage2", id:"389", group:'admin')
274
db = db.set(name:"Sage3", id:"5077", group:'admin')
275
276
it 'convert to string', ->
277
str = db.to_str()
278
expect(str).toEqual('{"name":"Sage0","active":' + JSON.stringify(time) + ',"id":"389","group":"user"}\n{"name":"Sage1","id":"123","group":"admin"}\n{"name":"Sage2","id":"389","group":"admin"}\n{"name":"Sage3","id":"5077","group":"admin"}')
279
280
it 'delete two records, then convert to string', ->
281
n = db.size
282
db = db.delete(id:'389')
283
expect(n - db.size).toEqual(2)
284
expect(db.to_str()).toEqual('{"name":"Sage1","id":"123","group":"admin"}\n{"name":"Sage3","id":"5077","group":"admin"}')
285
286
it 'convert from str', ->
287
db2 = from_str(str:db.to_str(), primary_keys: ['id', 'group'])
288
expect(db2.get()).toEqual(db.get())
289
# then delete and set other way
290
db = from_str(str:db2.to_str(), primary_keys: ['id', 'group'])
291
expect(db2.get()).toEqual(db.get())
292
293
294
describe 'test string_cols and patches --', ->
295
db = db2 = undefined
296
297
it "makes the db with a string col", ->
298
db = db_doc(primary_keys: ['id'], string_cols: ['input', 'input2'])
299
300
it 'adds a record', ->
301
db = db.set({id:0, input:"2+3"})
302
expect(db.get_one().toJS()).toEqual({id:0, input:'2+3'})
303
304
it 'modifies record and makes a patch', ->
305
db2 = db.set({id:0, input:"2+3 # add numbers"})
306
patch = db.make_patch(db2)
307
expect(JSON.stringify(patch)).toEqual('[1,[{"id":0,"input":[[[[0,"2+3"],[1," # add numbers"]],0,0,3,17]]}]]')
308
expect(db2.equals(db.apply_patch(patch))).toBe(true)
309
310
it 'modifies db further and makes a more subtle patch', ->
311
db2 = db2.set({id:0, input3:'abc'})
312
db3 = db2.set({id:0, input:"2 + 3 # add numbers", input2:"xyz", input3:'abc1'})
313
patch = db2.make_patch(db3)
314
expect(JSON.stringify(patch)).toEqual(
315
'[1,[{"id":0,"input":[[[[0,"2"],[-1,"+"],[1," + "],[0,"3 # "]],0,0,6,8]],"input3":"abc1","input2":"xyz"}]]')
316
expect(db2.apply_patch(patch).equals(db3)).toBe(true)
317
patch = db3.make_patch(db2)
318
expect(JSON.stringify(patch)).toEqual(
319
'[1,[{"id":0,"input2":null,"input":[[[[0,"2"],[-1," + "],[1,"+"],[0,"3 # "]],0,0,8,6]],"input3":"abc"}]]')
320
expect(db3.apply_patch(patch).equals(db2)).toBe(true)
321
322
describe 'make a complicated patch --', ->
323
324
it "make db, patch, and test", ->
325
v = [db_doc(primary_keys: ['id', 'table'], string_cols: ['input', 'input2'])]
326
v.push(v[v.length-1].set({id:0, table:'users', input:'2+3', input2:'3-5', input3:'2+7'}))
327
v.push(v[v.length-1].set({id:3, table:'other', foo:'bar'}))
328
v.push(v[v.length-1].set({id:'0', table:'users', input:'2-4'}))
329
v.push(v[v.length-1].set({id:'0', table:'users', input:'2+3', other_stuff:[{a:5,b:7}, {c:[1,2]}]}))
330
v.push(v[v.length-1].set({id:0, table:'users', input:'5+6', input2:null}))
331
v.push(v[v.length-1].delete({id:3, table:'other'}))
332
expect(v[v.length-1].size).toBe(2)
333
for i in [0...v.length]
334
expect(v[0].apply_patch(v[0].make_patch(v[i])).equals(v[i])).toBe(true)
335
expect(v[i].apply_patch(v[i].make_patch(v[0])).equals(v[0])).toBe(true)
336
expect(v[i].apply_patch(v[i].make_patch(v[2])).equals(v[2])).toBe(true)
337
338
describe 'ensure that big string in string_cols makes small patch --', ->
339
340
it 'make db with a big test string field', ->
341
db = db_doc(primary_keys: ['n'], string_cols: ['foo'])
342
db = db.set(n:0, foo:[0...10000].join(''))
343
db1 = db.set(n:0, foo:[0...10001].join(''))
344
expect(JSON.stringify(db.make_patch(db1)).length).toBe(74)
345
346
# This will be big
347
db2 = db1.set(n:0, foo2:[0...10000].join(''))
348
db3 = db2.set(n:0, foo2:[0...10001].join(''))
349
expect(JSON.stringify(db2.make_patch(db3)).length).toBe(38918)
350
351
352
describe 'test one-level merge setting of maps --', ->
353
354
it 'does some sets that illustrate merge setting', ->
355
db = db_doc(primary_keys: ['id'])
356
db = db.set(id:0, a:{b:1, c:2}, d:{e:{f:'g'}})
357
db = db.set(id:0, a:{b:3})
358
expect(db.get_one().toJS()).toEqual(id:0, a:{b:3, c:2}, d:{e:{f:'g'}})
359
# delete something using null
360
db = db.set(id:0, a:{c:null})
361
expect(db.get_one().toJS()).toEqual(id:0, a:{b:3}, d:{e:{f:'g'}})
362
# can only use null to delete one level deep
363
db = db.set(id:0, d:{e:{f:null}})
364
expect(db.get_one().toJS()).toEqual(id:0, a:{b:3}, d:{e:{f:null}})
365
366
367
it 'lists do not merge set', ->
368
db = db_doc(primary_keys: ['id'])
369
db = db.set(id:0, a:[2,4])
370
db = db.set(id:0, a:[2])
371
expect(db.get_one().toJS()).toEqual(id:0, a:[2])
372
373
374
describe 'test patches use merge maps --', ->
375
it "does a first test", ->
376
db = db_doc(primary_keys: ['id'])
377
db = db.set(id:0, a:{b:1, c:2}, d:{e:{f:'g'}})
378
db2 = db.set(id:0, a:{b:3})
379
patch = db.make_patch(db2)
380
expect(patch).toEqual([1, [{a: {b: 3}, id: 0}] ])
381
db3 = db2.set(id:0, d:{e:{f:null}})
382
patch = db2.make_patch(db3)
383
expect(patch).toEqual([ 1, [ { d: { e: { f: null } }, id: 0 } ] ])
384
385
it 'make a patch involving both a string patch and map merge patch', ->
386
db = db_doc(primary_keys: ['id'], string_cols:['name'])
387
db = db.set(id:0, name:'cocalc', a:{b:1, c:[1,2,3]})
388
db2 = db.set(id:0, name:'Cocalc', a:{b:['x','y'], c:[1,2,3], d:5})
389
patch = db.make_patch(db2)
390
expect(patch).toEqual([1,[{"id":0,"name":[[[[-1,"c"],[1,"C"],[0,"ocalc"]],0,0,6,6]],"a":{"b":["x","y"],"d":5}}]])
391
392
393