-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathKernelWeakTests.ns
457 lines (393 loc) · 10.1 KB
/
KernelWeakTests.ns
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
Newspeak3
'Newspeak'
class KernelWeakTests usingPlatform: p minitest: m gcAction: gc = (|
private TestContext = m TestContext.
private MessageNotUnderstood = p kernel MessageNotUnderstood.
private Ephemeron = p kernel Ephemeron.
private WeakArray = p kernel WeakArray.
private WeakMap = p kernel WeakMap.
private gcAction <[]> = gc.
|) (
public class EphemeronTests = TestContext () (
public testEphemeronAccessors = (
|
key = Object new.
value = Object new.
ephemeron = Ephemeron new.
|
assert: ephemeron key equals: nil.
assert: ephemeron value equals: nil.
assert: (ephemeron key: key) equals: ephemeron.
assert: ephemeron key equals: key.
assert: (ephemeron value: value) equals: ephemeron.
assert: ephemeron value equals: value.
)
public testEphemeronEphemerality1 = (
(* A simple weak reference. *)
|
key ::= Object new.
ephemeron = Ephemeron new.
|
ephemeron key: key; value: 42.
assert: ephemeron value equals: 42.
gcAction value.
assert: ephemeron value equals: 42.
key:: nil.
gcAction value.
assert: ephemeron value equals: nil.
)
public testEphemeronEphemerality2 = (
(* An indirect weak reference. *)
|
key1 ::= Object new.
key2 ::= Object new.
ephemeron1 = Ephemeron new.
ephemeron2 = Ephemeron new.
|
ephemeron1 key: key1; value: key2.
ephemeron2 key: key2; value: 42.
assert: ephemeron2 value equals: 42.
gcAction value.
assert: ephemeron2 value equals: 42.
key2:: nil.
gcAction value.
assert: ephemeron2 value equals: 42.
deny: ephemeron1 value equals: nil.
key1:: nil.
gcAction value.
assert: ephemeron1 value equals: nil.
assert: ephemeron2 value equals: nil.
)
public testEphemeronEphemerality3 = (
(* A cycle between ephemerons. *)
|
key1 ::= Object new.
key2 ::= Object new.
ephemeron1 = Ephemeron new.
ephemeron2 = Ephemeron new.
|
ephemeron1 key: key1; value: key2.
ephemeron2 key: key2; value: key1.
deny: ephemeron1 value equals: nil.
deny: ephemeron2 value equals: nil.
gcAction value.
deny: ephemeron1 value equals: nil.
deny: ephemeron2 value equals: nil.
key2:: nil.
gcAction value.
deny: ephemeron1 value equals: nil.
deny: ephemeron2 value equals: nil.
key1:: nil.
gcAction value.
assert: ephemeron1 value equals: nil.
assert: ephemeron2 value equals: nil.
)
public testEphemeronEphemerality4 = (
(* Ephemeron + weak array. *)
|
key ::= Object new.
ephemeron ::= Ephemeron new.
array = WeakArray new: 1.
|
ephemeron key: key; value: 42.
array at: 1 put: key.
gcAction value.
assert: ephemeron value equals: 42.
deny: (array at: 1) equals: nil.
key:: nil.
gcAction value.
assert: ephemeron value equals: nil.
assert: (array at: 1) equals: nil.
)
public testEphemeronEphemerality5a = (
(* An indirect weak reference. *)
|
key1 ::= Object new.
key2 ::= Object new.
value2 ::= Object new.
ephemeron1 ::= Ephemeron new.
ephemeron2 ::= Ephemeron new.
array = WeakArray new: 1.
|
ephemeron1 key: key1; value: key2.
ephemeron2 key: key2; value: value2.
array at: 1 put: value2.
deny: (array at: 1) equals: nil.
key2:: nil.
value2:: nil.
gcAction value.
deny: (array at: 1) equals: nil.
ephemeron2:: nil.
gcAction value.
assert: (array at: 1) equals: nil.
)
public testEphemeronEphemerality5b = (
(* An indirect weak reference. *)
|
key1 ::= Object new.
key2 ::= Object new.
value2 ::= Object new.
ephemeron1 ::= Ephemeron new.
ephemeron2 ::= Ephemeron new.
array = WeakArray new: 1.
|
ephemeron1 key: key1; value: key2.
ephemeron2 key: key2; value: value2.
array at: 1 put: value2.
deny: (array at: 1) equals: nil.
key2:: nil.
value2:: nil.
gcAction value.
deny: (array at: 1) equals: nil.
ephemeron1:: nil.
gcAction value.
assert: (array at: 1) equals: nil.
)
public testEphemeronEphemerality5c = (
(* An indirect weak reference. *)
|
key1 ::= Object new.
key2 ::= Object new.
value2 ::= Object new.
ephemeron1 ::= Ephemeron new.
ephemeron2 ::= Ephemeron new.
array = WeakArray new: 1.
|
ephemeron1 key: key1; value: key2.
ephemeron2 key: key2; value: value2.
array at: 1 put: value2.
deny: (array at: 1) equals: nil.
key2:: nil.
value2:: nil.
gcAction value.
deny: (array at: 1) equals: nil.
key1:: nil.
gcAction value.
assert: (array at: 1) equals: nil.
)
public testEphemeronEphemerality6 = (
(* Chain of ephemerons only reachable through ephemeral references *)
|
shallowKey ::= Object new.
deepKey ::= Object new.
array ::= Array new: 512.
temp
|
1 to: 511 do:
[:index |
temp:: Ephemeron new key: deepKey; value: index + 1000.
array at: index put: temp].
temp:: Ephemeron new key: shallowKey; value: deepKey.
128 timesRepeat:
[temp:: Ephemeron new key: shallowKey; value: temp].
array at: 512 put: temp.
temp:: nil.
deepKey:: nil.
1 to: 511 do:
[:index |
assert: (array at: index) value equals: index + 1000].
gcAction value.
1 to: 511 do:
[:index |
assert: (array at: index) value equals: index + 1000].
shallowKey:: nil.
gcAction value.
1 to: 512 do:
[:index |
assert: (array at: index) value equals: nil].
)
public testEphemeronEqualityIsIdentity = (
|
key = Object new.
value = Object new.
ephemeron = Ephemeron new.
ephemeron2 = Ephemeron new.
|
ephemeron key: key; value: value.
ephemeron2 key: key; value: value.
deny: ephemeron equals: ephemeron2.
)
public testEphemeronStableHash = (
|
key = Object new.
value = Object new.
key2 = Object new.
value2 = Object new.
ephemeron = Ephemeron new.
firstHash
|
firstHash:: ephemeron hash.
ephemeron key: key; value: value.
assert: ephemeron hash equals: firstHash.
ephemeron key: key2; value: value2.
assert: ephemeron hash equals: firstHash.
)
) : (
TEST_CONTEXT = ()
)
public class FrameTests = TestContext () (
deepStack: n = (
(* Not tail recursive. *)
^0 = n ifTrue: [0] ifFalse: [n + (deepStack: n - 1) + n]
)
public testFrameActivationLeak = (
|
array = WeakArray new: 1.
object ::= Object new.
|
array at: 1 put: object.
assert: (array at: 1) equals: object.
gcAction value.
assert: (array at: 1) equals: object.
(* Trigger stack overflow, causing this frame to be flushed to an activation. When control returns here, a new frame will be created for the activation. *)
assert: (deepStack: 1000) equals: 1001000.
(* Clears the temporary in the frame. *)
object:: nil.
gcAction value.
(* Check the activation is not retaining a copy of our cleared temporary. *)
assert: (array at: 1) equals: nil.
)
) : (
TEST_CONTEXT = ()
)
public class SymbolTests = TestContext () (
public testSymbolTableWeakness1 = (
| weakCell = WeakArray new: 1. |
(* Must not be a literal. *)
weakCell at: 1 put: ('Hopefully unique string', 1 printString) asSymbol.
gcAction value.
assert: (weakCell at: 1) equals: nil.
)
public testSymbolTableWeakness2 = (
| weakCell = Ephemeron new. |
(* Must not be a literal. *)
weakCell key: ('Hopefully unique string', 2 printString) asSymbol.
gcAction value.
assert: weakCell key equals: nil.
)
) : (
TEST_CONTEXT = ()
)
public class WeakArrayTests = TestContext () (
public testWeakArrayAt = (
| array = WeakArray new: 2. empty = WeakArray new: 0. |
array at: 1 put: 'apple'.
array at: 2 put: 'banana'.
assert: (array at: 1) equals: 'apple'.
assert: (array at: 2) equals: 'banana'.
should: [array at: 0] signal: Error.
should: [array at: 3] signal: Error.
should: [array at: -3] signal: Error.
should: [array at: nil] signal: Error.
should: [empty at: 1] signal: Error.
)
public testWeakArrayAtPut = (
| array = WeakArray new: 2. empty = WeakArray new: 0. |
assert: (array at: 1 put: 'apple') equals: 'apple'.
assert: (array at: 2 put: 'banana') equals: 'banana'.
should: [array at: 0 put: 'orange'] signal: Error.
should: [array at: 3 put: 'orange'] signal: Error.
should: [array at: -3 put: 'orange'] signal: Error.
should: [array at: nil put: 'orange'] signal: Error.
should: [empty at: 1 put: 'orange'] signal: Error.
)
public testWeakArrayFloatIndex = (
| array = WeakArray new: 1. |
should: [array at: 1 asFloat] signal: Error.
should: [array at: 1 asFloat put: 0] signal: Error.
)
public testWeakArrayIsEmpty = (
assert: (WeakArray new: 0) isEmpty.
deny: (WeakArray new: 1) isEmpty.
)
public testWeakArrayNew = (
assert: (WeakArray new: 0) size equals: 0.
assert: (WeakArray new: 500) size equals: 500.
should: [WeakArray new: -1] signal: Error.
should: [WeakArray new: '10'] signal: Error.
should: [WeakArray new: nil] signal: Error.
should: [WeakArray new] signal: MessageNotUnderstood.
)
public testWeakArrayWeakness = (
|
array = WeakArray new: 1.
object ::= Object new.
|
array at: 1 put: object.
assert: (array at: 1) equals: object.
gcAction value.
assert: (array at: 1) equals: object.
object:: nil.
gcAction value.
assert: (array at: 1) equals: nil.
)
) : (
TEST_CONTEXT = ()
)
public class WeakMapTests = TestContext () (
public testWeakMapBasic = (
|
map = WeakMap new.
key = Object new.
|
assert: map isKindOfWeakMap.
assert: (map at: key) equals: nil.
assert: (map at: key put: 42) equals: 42.
assert: (map at: key) equals: 42.
)
public testWeakMapGrowthExpand = (
|
map = WeakMap new.
keys = Array new: 4097.
values = Array new: 4097.
|
1 to: 4097 do:
[:index | | key value |
key:: Object new.
value:: Object new.
map at: key put: value.
assert: (map at: key) equals: value.
keys at: index put: key.
values at: index put: value].
1 to: 4097 do:
[:index | | key value |
key:: keys at: index.
value:: values at: index.
assert: (map at: key) equals: value].
)
public testWeakMapGrowthTreadmill = (
|
map = WeakMap new.
longTermKey = Object new.
longTermValue = Object new.
|
map at: longTermKey put: longTermValue.
1 to: 4097 do:
[:iteration | | key value |
key:: Object new.
value:: Object new.
map at: key put: value.
(iteration \\ 512) = 0 ifTrue: [gcAction value].
assert: (map at: key) equals: value].
assert: (map at: longTermKey) equals: longTermValue.
)
public testWeakMapWeakness = (
|
key ::= Object new.
map = WeakMap new.
array = WeakArray new: 1.
|
array at: 1 put: key.
map at: key put: 42.
gcAction value.
deny: (array at: 1) equals: nil.
assert: (map at: key) equals: 42.
key:: nil.
gcAction value.
assert: (array at: 1) equals: nil.
)
) : (
TEST_CONTEXT = ()
)
) : (
)