synapse 2.178.0__py311-none-any.whl → 2.180.0__py311-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of synapse might be problematic. Click here for more details.
- synapse/cortex.py +166 -31
- synapse/datamodel.py +47 -1
- synapse/exc.py +1 -0
- synapse/lib/aha.py +2 -1
- synapse/lib/ast.py +110 -76
- synapse/lib/base.py +12 -3
- synapse/lib/cell.py +150 -11
- synapse/lib/coro.py +14 -0
- synapse/lib/drive.py +551 -0
- synapse/lib/layer.py +1 -1
- synapse/lib/lmdbslab.py +2 -0
- synapse/lib/modelrev.py +5 -1
- synapse/lib/node.py +14 -4
- synapse/lib/schemas.py +97 -0
- synapse/lib/snap.py +36 -11
- synapse/lib/storm.py +9 -5
- synapse/lib/stormhttp.py +1 -0
- synapse/lib/stormlib/modelext.py +29 -3
- synapse/lib/stormlib/stix.py +44 -17
- synapse/lib/stormlib/vault.py +2 -2
- synapse/lib/stormtypes.py +1 -1
- synapse/lib/types.py +9 -0
- synapse/lib/version.py +2 -2
- synapse/lookup/pe.py +303 -38
- synapse/models/auth.py +2 -0
- synapse/models/dns.py +24 -1
- synapse/models/geopol.py +3 -0
- synapse/models/geospace.py +4 -1
- synapse/models/inet.py +1 -0
- synapse/models/infotech.py +135 -92
- synapse/models/person.py +5 -2
- synapse/models/telco.py +3 -0
- synapse/tests/test_cortex.py +45 -1
- synapse/tests/test_lib_aha.py +17 -0
- synapse/tests/test_lib_ast.py +231 -0
- synapse/tests/test_lib_cell.py +225 -0
- synapse/tests/test_lib_coro.py +12 -0
- synapse/tests/test_lib_layer.py +22 -0
- synapse/tests/test_lib_modelrev.py +7 -0
- synapse/tests/test_lib_node.py +12 -1
- synapse/tests/test_lib_storm.py +32 -7
- synapse/tests/test_lib_stormhttp.py +40 -0
- synapse/tests/test_lib_stormlib_modelext.py +55 -3
- synapse/tests/test_lib_stormlib_stix.py +15 -0
- synapse/tests/test_lib_stormlib_vault.py +11 -1
- synapse/tests/test_lib_stormtypes.py +5 -0
- synapse/tests/test_lib_types.py +9 -0
- synapse/tests/test_model_dns.py +8 -0
- synapse/tests/test_model_geopol.py +2 -0
- synapse/tests/test_model_geospace.py +3 -1
- synapse/tests/test_model_inet.py +10 -1
- synapse/tests/test_model_infotech.py +47 -0
- synapse/tests/test_model_person.py +2 -0
- synapse/tests/test_model_syn.py +11 -0
- synapse/tests/test_model_telco.py +2 -1
- synapse/tests/test_utils_stormcov.py +1 -1
- synapse/tools/changelog.py +28 -0
- {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/METADATA +1 -1
- {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/RECORD +62 -61
- {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/WHEEL +1 -1
- {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/LICENSE +0 -0
- {synapse-2.178.0.dist-info → synapse-2.180.0.dist-info}/top_level.txt +0 -0
synapse/tests/test_lib_ast.py
CHANGED
|
@@ -4100,3 +4100,234 @@ class AstTest(s_test.SynTest):
|
|
|
4100
4100
|
q = 'media:news=(m0,) [-:published]'
|
|
4101
4101
|
msgs = await core.stormlist(q, opts=aslow)
|
|
4102
4102
|
self.stormIsInErr('must have permission node.prop.del.media:news.published', msgs)
|
|
4103
|
+
|
|
4104
|
+
async def test_ast_path_links(self):
|
|
4105
|
+
|
|
4106
|
+
async with self.getTestCore() as core: # type: s_cortex.Cortex
|
|
4107
|
+
guid = s_common.guid()
|
|
4108
|
+
opts = {'vars': {'guid': guid}}
|
|
4109
|
+
|
|
4110
|
+
burr = (await core.nodes('[test:comp=(1234, burrito)]'))[0]
|
|
4111
|
+
guid = (await core.nodes('[test:guid=$guid :size=176 :tick=now]', opts=opts))[0]
|
|
4112
|
+
edge = (await core.nodes('[test:edge=(("test:guid", $guid), ("test:str", abcd))]', opts=opts))[0]
|
|
4113
|
+
comp = (await core.nodes('[test:complexcomp=(1234, STUFF) +#foo.bar]'))[0]
|
|
4114
|
+
tstr = (await core.nodes('[test:str=foobar :bar=(test:ro, "ackbar") :ndefs=((test:guid, $guid), (test:auto, "auto"))]', opts=opts))[0]
|
|
4115
|
+
arry = (await core.nodes('[test:arrayprop=* :ints=(3245, 678) :strs=("foo", "bar", "foobar")]'))[0]
|
|
4116
|
+
ostr = (await core.nodes('test:str=foo [ :bar=(test:ro, "ackbar") :ndefs=((test:int, 176), )]'))[0]
|
|
4117
|
+
pstr = (await core.nodes('test:str=bar [ :ndefs=((test:guid, $guid), (test:auto, "auto"), (test:ro, "ackbar"))]', opts=opts))[0]
|
|
4118
|
+
(await core.nodes('[test:arrayform=(1234, 176)]'))[0]
|
|
4119
|
+
(await core.nodes('[test:arrayform=(3245, 678)]'))[0]
|
|
4120
|
+
|
|
4121
|
+
await core.nodes('test:int=176 [ <(seen)+ { test:guid } ]')
|
|
4122
|
+
await core.nodes('test:int=176 [ <(someedge)+ { test:guid } ]')
|
|
4123
|
+
await core.nodes('test:complexcomp [ <(refs)+ { test:arrayprop } ]')
|
|
4124
|
+
await core.nodes('test:complexcomp [ +(concerns)> { test:ro } ]')
|
|
4125
|
+
await core.nodes('test:edge [ <(seen)+ { test:guid } ]')
|
|
4126
|
+
|
|
4127
|
+
small = (await core.nodes('test:int=176'))[0]
|
|
4128
|
+
large = (await core.nodes('test:int=1234'))[0]
|
|
4129
|
+
auto = (await core.nodes('test:auto'))[0]
|
|
4130
|
+
basetag = (await core.nodes('syn:tag=foo'))[0]
|
|
4131
|
+
tag = (await core.nodes('syn:tag=foo.bar'))[0]
|
|
4132
|
+
ro = (await core.nodes('test:ro'))[0]
|
|
4133
|
+
|
|
4134
|
+
def _assert_edge(msgs, src, edge, nidx=0, eidx=0):
|
|
4135
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
4136
|
+
links = nodes[nidx][1].get('links')
|
|
4137
|
+
self.nn(links)
|
|
4138
|
+
self.lt(eidx, len(links))
|
|
4139
|
+
self.eq(links[eidx], (src.iden(), edge))
|
|
4140
|
+
|
|
4141
|
+
opts = {'links': True}
|
|
4142
|
+
|
|
4143
|
+
# non-runtsafe lift could be anything
|
|
4144
|
+
msgs = await core.stormlist('test:str=foobar $newform=$node.props.bar.0 *$newform', opts={'links': True, 'vars': {'form': 'inet:ipv4'}})
|
|
4145
|
+
_assert_edge(msgs, tstr, {'type': 'runtime'}, nidx=1)
|
|
4146
|
+
|
|
4147
|
+
# FormPivot
|
|
4148
|
+
# -> baz:ndef
|
|
4149
|
+
msgs = await core.stormlist('test:guid -> test:edge:n1', opts=opts)
|
|
4150
|
+
_assert_edge(msgs, guid, {'type': 'prop', 'prop': 'n1', 'reverse': True})
|
|
4151
|
+
|
|
4152
|
+
# plain old pivot
|
|
4153
|
+
msgs = await core.stormlist('test:int=176 -> test:guid:size', opts=opts)
|
|
4154
|
+
_assert_edge(msgs, small, {'type': 'prop', 'prop': 'size', 'reverse': True})
|
|
4155
|
+
|
|
4156
|
+
# graph edge dest form uses n1 automagically
|
|
4157
|
+
msgs = await core.stormlist('test:guid -> test:edge', opts=opts)
|
|
4158
|
+
_assert_edge(msgs, guid, {'type': 'prop', 'prop': 'n1', 'reverse': True})
|
|
4159
|
+
|
|
4160
|
+
# <syn:tag> -> <form>
|
|
4161
|
+
msgs = await core.stormlist('syn:tag=foo.bar -> test:complexcomp', opts=opts)
|
|
4162
|
+
_assert_edge(msgs, tag, {'type': 'tag', 'tag': 'foo.bar', 'reverse': True})
|
|
4163
|
+
|
|
4164
|
+
# source node is a graph edge, use n2
|
|
4165
|
+
msgs = await core.stormlist('test:edge -> test:str', opts=opts)
|
|
4166
|
+
_assert_edge(msgs, edge, {'type': 'prop', 'prop': 'n2'})
|
|
4167
|
+
|
|
4168
|
+
# refs out - prop
|
|
4169
|
+
msgs = await core.stormlist('test:complexcomp -> test:int', opts=opts)
|
|
4170
|
+
_assert_edge(msgs, comp, {'type': 'prop', 'prop': 'foo'})
|
|
4171
|
+
|
|
4172
|
+
# refs out - array
|
|
4173
|
+
msgs = await core.stormlist('test:arrayprop -> test:int', opts=opts)
|
|
4174
|
+
_assert_edge(msgs, arry, {'type': 'prop', 'prop': 'ints'})
|
|
4175
|
+
_assert_edge(msgs, arry, {'type': 'prop', 'prop': 'ints'}, nidx=1)
|
|
4176
|
+
|
|
4177
|
+
# refs out - ndef
|
|
4178
|
+
msgs = await core.stormlist('test:str -> test:ro', opts=opts)
|
|
4179
|
+
_assert_edge(msgs, pstr, {'type': 'prop', 'prop': 'ndefs'})
|
|
4180
|
+
_assert_edge(msgs, ostr, {'type': 'prop', 'prop': 'bar'}, nidx=1)
|
|
4181
|
+
_assert_edge(msgs, tstr, {'type': 'prop', 'prop': 'bar'}, nidx=2)
|
|
4182
|
+
|
|
4183
|
+
# refs out - ndefarray
|
|
4184
|
+
msgs = await core.stormlist('test:str -> test:auto', opts=opts)
|
|
4185
|
+
_assert_edge(msgs, pstr, {'type': 'prop', 'prop': 'ndefs'})
|
|
4186
|
+
_assert_edge(msgs, tstr, {'type': 'prop', 'prop': 'ndefs'}, nidx=1)
|
|
4187
|
+
|
|
4188
|
+
# reverse prop refs
|
|
4189
|
+
msgs = await core.stormlist('test:int -> test:complexcomp', opts=opts)
|
|
4190
|
+
_assert_edge(msgs, large, {'type': 'prop', 'prop': 'foo', 'reverse': True})
|
|
4191
|
+
|
|
4192
|
+
# reverse array refs
|
|
4193
|
+
msgs = await core.stormlist('test:int -> test:arrayprop', opts=opts)
|
|
4194
|
+
sixer = (await core.nodes('test:int=678'))[0]
|
|
4195
|
+
thou = (await core.nodes('test:int=3245'))[0]
|
|
4196
|
+
_assert_edge(msgs, sixer, {'type': 'prop', 'prop': 'ints', 'reverse': True})
|
|
4197
|
+
_assert_edge(msgs, thou, {'type': 'prop', 'prop': 'ints', 'reverse': True}, nidx=1)
|
|
4198
|
+
|
|
4199
|
+
# reverse ndef refs
|
|
4200
|
+
msgs = await core.stormlist('test:ro -> test:str', opts=opts)
|
|
4201
|
+
_assert_edge(msgs, ro, {'type': 'prop', 'prop': 'bar', 'reverse': True})
|
|
4202
|
+
|
|
4203
|
+
# reverse ndefarray refs
|
|
4204
|
+
msgs = await core.stormlist('test:auto -> test:str', opts=opts)
|
|
4205
|
+
_assert_edge(msgs, auto, {'type': 'prop', 'prop': 'ndefs', 'reverse': True})
|
|
4206
|
+
|
|
4207
|
+
# PivotOut syn:tag
|
|
4208
|
+
msgs = await core.stormlist('syn:tag -> *', opts=opts)
|
|
4209
|
+
_assert_edge(msgs, basetag, {'type': 'tag', 'tag': 'foo', 'reverse': True})
|
|
4210
|
+
_assert_edge(msgs, tag, {'type': 'tag', 'tag': 'foo.bar', 'reverse': True}, nidx=1)
|
|
4211
|
+
|
|
4212
|
+
# PivotOut edge uses n2 automatically
|
|
4213
|
+
msgs = await core.stormlist('test:edge -> *', opts=opts)
|
|
4214
|
+
_assert_edge(msgs, edge, {'type': 'prop', 'prop': 'n2'})
|
|
4215
|
+
|
|
4216
|
+
# PivotOut prop
|
|
4217
|
+
msgs = await core.stormlist('test:guid -> *', opts=opts)
|
|
4218
|
+
_assert_edge(msgs, guid, {'type': 'prop', 'prop': 'size'})
|
|
4219
|
+
|
|
4220
|
+
# PivotOut prop array
|
|
4221
|
+
msgs = await core.stormlist('test:arrayprop -> *', opts=opts)
|
|
4222
|
+
_assert_edge(msgs, arry, {'type': 'prop', 'prop': 'ints'})
|
|
4223
|
+
_assert_edge(msgs, arry, {'type': 'prop', 'prop': 'ints'}, nidx=1)
|
|
4224
|
+
_assert_edge(msgs, arry, {'type': 'prop', 'prop': 'strs'}, nidx=2)
|
|
4225
|
+
_assert_edge(msgs, arry, {'type': 'prop', 'prop': 'strs'}, nidx=3)
|
|
4226
|
+
_assert_edge(msgs, arry, {'type': 'prop', 'prop': 'strs'}, nidx=4)
|
|
4227
|
+
|
|
4228
|
+
# PivotOut prop ndef and ndef array
|
|
4229
|
+
msgs = await core.stormlist('test:str=foobar -> *', opts=opts)
|
|
4230
|
+
_assert_edge(msgs, tstr, {'type': 'prop', 'prop': 'bar'})
|
|
4231
|
+
_assert_edge(msgs, tstr, {'type': 'prop', 'prop': 'ndefs'}, nidx=1)
|
|
4232
|
+
_assert_edge(msgs, tstr, {'type': 'prop', 'prop': 'ndefs'}, nidx=2)
|
|
4233
|
+
|
|
4234
|
+
# PivotToTags
|
|
4235
|
+
msgs = await core.stormlist('test:complexcomp -> #', opts=opts)
|
|
4236
|
+
_assert_edge(msgs, comp, {'type': 'tag', 'tag': 'foo.bar'})
|
|
4237
|
+
|
|
4238
|
+
# PivotIn prop
|
|
4239
|
+
msgs = await core.stormlist('test:int=176 <- *', opts=opts)
|
|
4240
|
+
_assert_edge(msgs, small, {'type': 'prop', 'prop': 'size', 'reverse': True})
|
|
4241
|
+
|
|
4242
|
+
# PivotIn array prop
|
|
4243
|
+
msgs = await core.stormlist('test:str=foobar <- *', opts=opts)
|
|
4244
|
+
_assert_edge(msgs, tstr, {'type': 'prop', 'prop': 'strs', 'reverse': True})
|
|
4245
|
+
|
|
4246
|
+
# PivotIn edge uses n1 automatically
|
|
4247
|
+
msgs = await core.stormlist('test:edge <- *', opts=opts)
|
|
4248
|
+
_assert_edge(msgs, edge, {'type': 'prop', 'prop': 'n1', 'reverse': True})
|
|
4249
|
+
|
|
4250
|
+
# PivotIn ndef
|
|
4251
|
+
msgs = await core.stormlist('test:ro <- *', opts=opts)
|
|
4252
|
+
_assert_edge(msgs, ro, {'type': 'prop', 'prop': 'bar', 'reverse': True})
|
|
4253
|
+
|
|
4254
|
+
# PivotIn array ndef
|
|
4255
|
+
msgs = await core.stormlist('test:auto <- *', opts=opts)
|
|
4256
|
+
_assert_edge(msgs, auto, {'type': 'prop', 'prop': 'ndefs', 'reverse': True})
|
|
4257
|
+
|
|
4258
|
+
# PivotInFrom "<- edge"
|
|
4259
|
+
abcd = (await core.nodes('test:str=abcd'))[0]
|
|
4260
|
+
msgs = await core.stormlist('test:str <- test:edge', opts=opts)
|
|
4261
|
+
_assert_edge(msgs, abcd, {'type': 'prop', 'prop': 'n2', 'reverse': True})
|
|
4262
|
+
|
|
4263
|
+
# PivotInFrom "edge <- form"
|
|
4264
|
+
msgs = await core.stormlist('test:edge <- test:guid', opts=opts)
|
|
4265
|
+
_assert_edge(msgs, edge, {'type': 'prop', 'prop': 'n1', 'reverse': True})
|
|
4266
|
+
|
|
4267
|
+
# PropPivotOut prop
|
|
4268
|
+
msgs = await core.stormlist('test:guid :size -> *', opts=opts)
|
|
4269
|
+
_assert_edge(msgs, guid, {'type': 'prop', 'prop': 'size'})
|
|
4270
|
+
|
|
4271
|
+
# PropPivotOut ndef
|
|
4272
|
+
msgs = await core.stormlist('test:str=foobar :bar -> *', opts=opts)
|
|
4273
|
+
_assert_edge(msgs, tstr, {'type': 'prop', 'prop': 'bar'})
|
|
4274
|
+
|
|
4275
|
+
# PropPivotOut array
|
|
4276
|
+
msgs = await core.stormlist('test:arrayprop :ints -> *', opts=opts)
|
|
4277
|
+
_assert_edge(msgs, arry, {'type': 'prop', 'prop': 'ints'})
|
|
4278
|
+
_assert_edge(msgs, arry, {'type': 'prop', 'prop': 'ints'}, nidx=1)
|
|
4279
|
+
|
|
4280
|
+
# PropPivotOut array ndef
|
|
4281
|
+
msgs = await core.stormlist('test:str=foobar :ndefs -> *', opts=opts)
|
|
4282
|
+
_assert_edge(msgs, tstr, {'type': 'prop', 'prop': 'ndefs'})
|
|
4283
|
+
_assert_edge(msgs, tstr, {'type': 'prop', 'prop': 'ndefs'}, nidx=1)
|
|
4284
|
+
|
|
4285
|
+
# PropPivot prop to form
|
|
4286
|
+
msgs = await core.stormlist('test:guid :size -> test:int', opts=opts)
|
|
4287
|
+
_assert_edge(msgs, guid, {'type': 'prop', 'prop': 'size'})
|
|
4288
|
+
|
|
4289
|
+
# PropPivot ndef prop
|
|
4290
|
+
msgs = await core.stormlist('test:str :bar -> test:ro', opts=opts)
|
|
4291
|
+
_assert_edge(msgs, ostr, {'type': 'prop', 'prop': 'bar'})
|
|
4292
|
+
_assert_edge(msgs, tstr, {'type': 'prop', 'prop': 'bar'}, nidx=1)
|
|
4293
|
+
|
|
4294
|
+
# PropPivot array
|
|
4295
|
+
msgs = await core.stormlist('test:arrayprop :ints -> test:int', opts=opts)
|
|
4296
|
+
_assert_edge(msgs, arry, {'type': 'prop', 'prop': 'ints'})
|
|
4297
|
+
_assert_edge(msgs, arry, {'type': 'prop', 'prop': 'ints'}, nidx=1)
|
|
4298
|
+
|
|
4299
|
+
# PropPivot dst array primary prop
|
|
4300
|
+
msgs = await core.stormlist('test:guid :size -> test:arrayform', opts=opts)
|
|
4301
|
+
_assert_edge(msgs, guid, {'type': 'prop', 'prop': 'size'})
|
|
4302
|
+
|
|
4303
|
+
# PropPivot oops all arrays
|
|
4304
|
+
msgs = await core.stormlist('test:arrayprop :ints -> test:arrayform', opts=opts)
|
|
4305
|
+
_assert_edge(msgs, arry, {'type': 'prop', 'prop': 'ints'})
|
|
4306
|
+
|
|
4307
|
+
# PropPivot src ndef array
|
|
4308
|
+
msgs = await core.stormlist('test:str=foobar :ndefs -> test:guid', opts=opts)
|
|
4309
|
+
_assert_edge(msgs, tstr, {'type': 'prop', 'prop': 'ndefs'})
|
|
4310
|
+
|
|
4311
|
+
# prop to prop
|
|
4312
|
+
msgs = await core.stormlist('test:comp :hehe -> test:complexcomp:foo', opts=opts)
|
|
4313
|
+
_assert_edge(msgs, burr, {'type': 'prop', 'prop': 'hehe', 'dest': 'test:complexcomp:foo'})
|
|
4314
|
+
|
|
4315
|
+
# N1Walk
|
|
4316
|
+
msgs = await core.stormlist('test:arrayprop -(*)> *', opts=opts)
|
|
4317
|
+
_assert_edge(msgs, arry, {'type': 'edge', 'verb': 'refs'})
|
|
4318
|
+
|
|
4319
|
+
# N2Walk
|
|
4320
|
+
msgs = await core.stormlist('test:edge <(*)- *', opts=opts)
|
|
4321
|
+
_assert_edge(msgs, edge, {'type': 'edge', 'verb': 'seen', 'reverse': True})
|
|
4322
|
+
|
|
4323
|
+
# N1WalkNPivo
|
|
4324
|
+
msgs = await core.stormlist('test:complexcomp --> *', opts=opts)
|
|
4325
|
+
_assert_edge(msgs, comp, {'type': 'prop', 'prop': 'foo'})
|
|
4326
|
+
_assert_edge(msgs, comp, {'type': 'edge', 'verb': 'concerns'}, nidx=1)
|
|
4327
|
+
|
|
4328
|
+
# N2WalNkPivo
|
|
4329
|
+
msgs = await core.stormlist('test:int=176 <-- *', opts=opts)
|
|
4330
|
+
_assert_edge(msgs, small, {'type': 'prop', 'prop': 'size', 'reverse': True})
|
|
4331
|
+
_assert_edge(msgs, small, {'type': 'prop', 'prop': 'ndefs', 'reverse': True}, nidx=1)
|
|
4332
|
+
_assert_edge(msgs, small, {'type': 'edge', 'verb': 'seen', 'reverse': True}, nidx=2)
|
|
4333
|
+
_assert_edge(msgs, small, {'type': 'edge', 'verb': 'someedge', 'reverse': True}, nidx=3)
|
synapse/tests/test_lib_cell.py
CHANGED
|
@@ -28,6 +28,7 @@ import synapse.lib.base as s_base
|
|
|
28
28
|
import synapse.lib.cell as s_cell
|
|
29
29
|
import synapse.lib.coro as s_coro
|
|
30
30
|
import synapse.lib.link as s_link
|
|
31
|
+
import synapse.lib.drive as s_drive
|
|
31
32
|
import synapse.lib.nexus as s_nexus
|
|
32
33
|
import synapse.lib.certdir as s_certdir
|
|
33
34
|
import synapse.lib.msgpack as s_msgpack
|
|
@@ -155,8 +156,217 @@ async def altAuthCtor(cell):
|
|
|
155
156
|
cell.onfini(auth.fini)
|
|
156
157
|
return auth
|
|
157
158
|
|
|
159
|
+
testDataSchema_v0 = {
|
|
160
|
+
'type': 'object',
|
|
161
|
+
'properties': {
|
|
162
|
+
'type': {'type': 'string'},
|
|
163
|
+
'size': {'type': 'number'},
|
|
164
|
+
},
|
|
165
|
+
'required': ['type', 'size'],
|
|
166
|
+
'additionalProperties': False,
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
testDataSchema_v1 = {
|
|
170
|
+
'type': 'object',
|
|
171
|
+
'properties': {
|
|
172
|
+
'type': {'type': 'string'},
|
|
173
|
+
'size': {'type': 'number'},
|
|
174
|
+
'woot': {'type': 'string'},
|
|
175
|
+
},
|
|
176
|
+
'required': ['type', 'size', 'woot'],
|
|
177
|
+
'additionalProperties': False,
|
|
178
|
+
}
|
|
179
|
+
|
|
158
180
|
class CellTest(s_t_utils.SynTest):
|
|
159
181
|
|
|
182
|
+
async def test_cell_drive(self):
|
|
183
|
+
|
|
184
|
+
async with self.getTestCell() as cell:
|
|
185
|
+
|
|
186
|
+
with self.raises(s_exc.BadName):
|
|
187
|
+
s_drive.reqValidName('A' * 512)
|
|
188
|
+
|
|
189
|
+
info = {'name': 'users'}
|
|
190
|
+
pathinfo = await cell.addDriveItem(info)
|
|
191
|
+
|
|
192
|
+
info = {'name': 'root'}
|
|
193
|
+
pathinfo = await cell.addDriveItem(info, path='users')
|
|
194
|
+
|
|
195
|
+
with self.raises(s_exc.DupIden):
|
|
196
|
+
await cell.drive.addItemInfo(pathinfo[-1], path='users')
|
|
197
|
+
|
|
198
|
+
rootdir = pathinfo[-1].get('iden')
|
|
199
|
+
self.eq(0, pathinfo[-1].get('kids'))
|
|
200
|
+
|
|
201
|
+
info = {'name': 'win32k.sys', 'type': 'hehe'}
|
|
202
|
+
with self.raises(s_exc.NoSuchType):
|
|
203
|
+
info = await cell.addDriveItem(info, reldir=rootdir)
|
|
204
|
+
|
|
205
|
+
infos = [i async for i in cell.getDriveKids(s_drive.rootdir)]
|
|
206
|
+
self.len(1, infos)
|
|
207
|
+
self.eq(1, infos[0].get('kids'))
|
|
208
|
+
self.eq('users', infos[0].get('name'))
|
|
209
|
+
|
|
210
|
+
# TODO how to handle iden match with additional property mismatch
|
|
211
|
+
|
|
212
|
+
await cell.drive.setTypeSchema('woot', testDataSchema_v0)
|
|
213
|
+
|
|
214
|
+
info = {'name': 'win32k.sys', 'type': 'woot'}
|
|
215
|
+
info = await cell.addDriveItem(info, reldir=rootdir)
|
|
216
|
+
|
|
217
|
+
iden = info[-1].get('iden')
|
|
218
|
+
|
|
219
|
+
tick = s_common.now()
|
|
220
|
+
rootuser = cell.auth.rootuser.iden
|
|
221
|
+
|
|
222
|
+
with self.raises(s_exc.SchemaViolation):
|
|
223
|
+
versinfo = {'version': (1, 0, 0), 'updated': tick, 'updater': rootuser}
|
|
224
|
+
await cell.setDriveData(iden, versinfo, {'newp': 'newp'})
|
|
225
|
+
|
|
226
|
+
versinfo = {'version': (1, 1, 0), 'updated': tick + 10, 'updater': rootuser}
|
|
227
|
+
info, versinfo = await cell.setDriveData(iden, versinfo, {'type': 'haha', 'size': 20})
|
|
228
|
+
self.eq(info.get('version'), (1, 1, 0))
|
|
229
|
+
self.eq(versinfo.get('version'), (1, 1, 0))
|
|
230
|
+
|
|
231
|
+
versinfo = {'version': (1, 0, 0), 'updated': tick, 'updater': rootuser}
|
|
232
|
+
info, versinfo = await cell.setDriveData(iden, versinfo, {'type': 'hehe', 'size': 0})
|
|
233
|
+
self.eq(info.get('version'), (1, 1, 0))
|
|
234
|
+
self.eq(versinfo.get('version'), (1, 0, 0))
|
|
235
|
+
|
|
236
|
+
versinfo10, data10 = await cell.getDriveData(iden, vers=(1, 0, 0))
|
|
237
|
+
self.eq(versinfo10.get('updated'), tick)
|
|
238
|
+
self.eq(versinfo10.get('updater'), rootuser)
|
|
239
|
+
self.eq(versinfo10.get('version'), (1, 0, 0))
|
|
240
|
+
|
|
241
|
+
versinfo11, data11 = await cell.getDriveData(iden, vers=(1, 1, 0))
|
|
242
|
+
self.eq(versinfo11.get('updated'), tick + 10)
|
|
243
|
+
self.eq(versinfo11.get('updater'), rootuser)
|
|
244
|
+
self.eq(versinfo11.get('version'), (1, 1, 0))
|
|
245
|
+
|
|
246
|
+
versions = [vers async for vers in cell.getDriveDataVersions(iden)]
|
|
247
|
+
self.len(2, versions)
|
|
248
|
+
self.eq(versions[0], versinfo11)
|
|
249
|
+
self.eq(versions[1], versinfo10)
|
|
250
|
+
|
|
251
|
+
info = await cell.delDriveData(iden, vers=(0, 0, 0))
|
|
252
|
+
|
|
253
|
+
versions = [vers async for vers in cell.getDriveDataVersions(iden)]
|
|
254
|
+
self.len(2, versions)
|
|
255
|
+
self.eq(versions[0], versinfo11)
|
|
256
|
+
self.eq(versions[1], versinfo10)
|
|
257
|
+
|
|
258
|
+
info = await cell.delDriveData(iden, vers=(1, 1, 0))
|
|
259
|
+
self.eq(info.get('updated'), tick)
|
|
260
|
+
self.eq(info.get('version'), (1, 0, 0))
|
|
261
|
+
|
|
262
|
+
info = await cell.delDriveData(iden, vers=(1, 0, 0))
|
|
263
|
+
self.eq(info.get('size'), 0)
|
|
264
|
+
self.eq(info.get('version'), (0, 0, 0))
|
|
265
|
+
self.none(info.get('updated'))
|
|
266
|
+
self.none(info.get('updater'))
|
|
267
|
+
|
|
268
|
+
# repopulate a couple data versions to test migration and delete
|
|
269
|
+
versinfo = {'version': (1, 0, 0), 'updated': tick, 'updater': rootuser}
|
|
270
|
+
info, versinfo = await cell.setDriveData(iden, versinfo, {'type': 'hehe', 'size': 0})
|
|
271
|
+
versinfo = {'version': (1, 1, 0), 'updated': tick + 10, 'updater': rootuser}
|
|
272
|
+
info, versinfo = await cell.setDriveData(iden, versinfo, {'type': 'haha', 'size': 17})
|
|
273
|
+
self.eq(versinfo, (await cell.getDriveData(iden))[0])
|
|
274
|
+
|
|
275
|
+
# This will be done by the cell in a cell storage version migration...
|
|
276
|
+
async def migrate_v1(info, versinfo, data):
|
|
277
|
+
data['woot'] = 'woot'
|
|
278
|
+
return data
|
|
279
|
+
|
|
280
|
+
await cell.drive.setTypeSchema('woot', testDataSchema_v1, migrate_v1)
|
|
281
|
+
|
|
282
|
+
versinfo, data = await cell.getDriveData(iden, vers=(1, 0, 0))
|
|
283
|
+
self.eq('woot', data.get('woot'))
|
|
284
|
+
|
|
285
|
+
versinfo, data = await cell.getDriveData(iden, vers=(1, 1, 0))
|
|
286
|
+
self.eq('woot', data.get('woot'))
|
|
287
|
+
|
|
288
|
+
self.nn(await cell.getDriveInfo(iden))
|
|
289
|
+
self.len(2, [vers async for vers in cell.getDriveDataVersions(iden)])
|
|
290
|
+
|
|
291
|
+
await cell.delDriveData(iden)
|
|
292
|
+
self.len(1, [vers async for vers in cell.getDriveDataVersions(iden)])
|
|
293
|
+
|
|
294
|
+
await cell.delDriveInfo(iden)
|
|
295
|
+
|
|
296
|
+
self.none(await cell.getDriveInfo(iden))
|
|
297
|
+
self.len(0, [vers async for vers in cell.getDriveDataVersions(iden)])
|
|
298
|
+
|
|
299
|
+
with self.raises(s_exc.NoSuchPath):
|
|
300
|
+
await cell.getDrivePath('users/root/win32k.sys')
|
|
301
|
+
|
|
302
|
+
pathinfo = await cell.addDrivePath('foo/bar/baz')
|
|
303
|
+
self.len(3, pathinfo)
|
|
304
|
+
self.eq('foo', pathinfo[0].get('name'))
|
|
305
|
+
self.eq(1, pathinfo[0].get('kids'))
|
|
306
|
+
self.eq('bar', pathinfo[1].get('name'))
|
|
307
|
+
self.eq(1, pathinfo[1].get('kids'))
|
|
308
|
+
self.eq('baz', pathinfo[2].get('name'))
|
|
309
|
+
self.eq(0, pathinfo[2].get('kids'))
|
|
310
|
+
|
|
311
|
+
self.eq(pathinfo, await cell.addDrivePath('foo/bar/baz'))
|
|
312
|
+
|
|
313
|
+
baziden = pathinfo[2].get('iden')
|
|
314
|
+
self.eq(pathinfo, await cell.drive.getItemPath(baziden))
|
|
315
|
+
|
|
316
|
+
info = await cell.setDriveInfoPerm(baziden, {'users': {rootuser: 3}, 'roles': {}})
|
|
317
|
+
self.eq(3, info['perm']['users'][rootuser])
|
|
318
|
+
|
|
319
|
+
with self.raises(s_exc.NoSuchIden):
|
|
320
|
+
# s_drive.rootdir is all 00s... ;)
|
|
321
|
+
await cell.setDriveInfoPerm(s_drive.rootdir, {'users': {}, 'roles': {}})
|
|
322
|
+
|
|
323
|
+
await cell.addDrivePath('hehe/haha')
|
|
324
|
+
pathinfo = await cell.setDriveInfoPath(baziden, 'hehe/haha/hoho')
|
|
325
|
+
|
|
326
|
+
self.eq('hoho', pathinfo[-1].get('name'))
|
|
327
|
+
self.eq(baziden, pathinfo[-1].get('iden'))
|
|
328
|
+
|
|
329
|
+
self.true(await cell.drive.hasPathInfo('hehe/haha/hoho'))
|
|
330
|
+
self.false(await cell.drive.hasPathInfo('foo/bar/baz'))
|
|
331
|
+
|
|
332
|
+
pathinfo = await cell.getDrivePath('foo/bar')
|
|
333
|
+
self.eq(0, pathinfo[-1].get('kids'))
|
|
334
|
+
|
|
335
|
+
pathinfo = await cell.getDrivePath('hehe/haha')
|
|
336
|
+
self.eq(1, pathinfo[-1].get('kids'))
|
|
337
|
+
|
|
338
|
+
with self.raises(s_exc.DupName):
|
|
339
|
+
iden = pathinfo[-2].get('iden')
|
|
340
|
+
name = pathinfo[-1].get('name')
|
|
341
|
+
cell.drive.reqFreeStep(iden, name)
|
|
342
|
+
|
|
343
|
+
walks = [item async for item in cell.drive.walkPathInfo('hehe')]
|
|
344
|
+
self.len(3, walks)
|
|
345
|
+
# confirm walked paths are yielded depth first...
|
|
346
|
+
self.eq('hoho', walks[0].get('name'))
|
|
347
|
+
self.eq('haha', walks[1].get('name'))
|
|
348
|
+
self.eq('hehe', walks[2].get('name'))
|
|
349
|
+
|
|
350
|
+
iden = walks[2].get('iden')
|
|
351
|
+
walks = [item async for item in cell.drive.walkItemInfo(iden)]
|
|
352
|
+
self.len(3, walks)
|
|
353
|
+
self.eq('hoho', walks[0].get('name'))
|
|
354
|
+
self.eq('haha', walks[1].get('name'))
|
|
355
|
+
self.eq('hehe', walks[2].get('name'))
|
|
356
|
+
|
|
357
|
+
self.none(cell.drive.getTypeSchema('newp'))
|
|
358
|
+
|
|
359
|
+
cell.drive.validators.pop('woot')
|
|
360
|
+
self.nn(cell.drive.getTypeValidator('woot'))
|
|
361
|
+
|
|
362
|
+
# move to root dir
|
|
363
|
+
pathinfo = await cell.setDriveInfoPath(baziden, 'zipzop')
|
|
364
|
+
self.len(1, pathinfo)
|
|
365
|
+
self.eq(s_drive.rootdir, pathinfo[-1].get('parent'))
|
|
366
|
+
|
|
367
|
+
pathinfo = await cell.setDriveInfoPath(baziden, 'hehe/haha/hoho')
|
|
368
|
+
self.len(3, pathinfo)
|
|
369
|
+
|
|
160
370
|
async def test_cell_auth(self):
|
|
161
371
|
|
|
162
372
|
with self.getTestDir() as dirn:
|
|
@@ -860,6 +1070,7 @@ class CellTest(s_t_utils.SynTest):
|
|
|
860
1070
|
self.nn(slab['xactops'])
|
|
861
1071
|
self.nn(slab['mapsize'])
|
|
862
1072
|
self.nn(slab['readonly'])
|
|
1073
|
+
self.nn(slab['readahead'])
|
|
863
1074
|
self.nn(slab['lockmemory'])
|
|
864
1075
|
self.nn(slab['recovering'])
|
|
865
1076
|
|
|
@@ -2914,3 +3125,17 @@ class CellTest(s_t_utils.SynTest):
|
|
|
2914
3125
|
|
|
2915
3126
|
async with self.getTestCell(s_cell.Cell, dirn=dirn):
|
|
2916
3127
|
pass
|
|
3128
|
+
|
|
3129
|
+
async def test_cell_initslab_fini(self):
|
|
3130
|
+
class SlabCell(s_cell.Cell):
|
|
3131
|
+
async def initServiceStorage(self):
|
|
3132
|
+
self.long_lived_slab = await self._initSlabFile(os.path.join(self.dirn, 'slabs', 'long.lmdb'))
|
|
3133
|
+
short_slab = await self._initSlabFile(os.path.join(self.dirn, 'slabs', 'short.lmdb'), ephemeral=True)
|
|
3134
|
+
self.short_slab_path = short_slab.lenv.path()
|
|
3135
|
+
await short_slab.fini()
|
|
3136
|
+
|
|
3137
|
+
async with self.getTestCell(SlabCell) as cell:
|
|
3138
|
+
self.true(os.path.isdir(cell.short_slab_path))
|
|
3139
|
+
self.isin(cell.long_lived_slab.fini, cell._fini_funcs)
|
|
3140
|
+
slabs = [s for s in cell.tofini if isinstance(s, s_lmdbslab.Slab) and s.lenv.path() == cell.short_slab_path]
|
|
3141
|
+
self.len(0, slabs)
|
synapse/tests/test_lib_coro.py
CHANGED
|
@@ -41,6 +41,18 @@ def nopickle():
|
|
|
41
41
|
|
|
42
42
|
class CoroTest(s_t_utils.SynTest):
|
|
43
43
|
|
|
44
|
+
async def test_coro_chunks(self):
|
|
45
|
+
async def agen():
|
|
46
|
+
for i in range(101):
|
|
47
|
+
yield i
|
|
48
|
+
|
|
49
|
+
chunks = []
|
|
50
|
+
async for chunk in s_coro.chunks(agen()):
|
|
51
|
+
chunks.append(chunk)
|
|
52
|
+
|
|
53
|
+
self.len(1, chunks[1])
|
|
54
|
+
self.len(100, chunks[0])
|
|
55
|
+
|
|
44
56
|
async def test_coro_event(self):
|
|
45
57
|
|
|
46
58
|
evnt = s_coro.Event()
|
synapse/tests/test_lib_layer.py
CHANGED
|
@@ -2216,3 +2216,25 @@ class LayerTest(s_t_utils.SynTest):
|
|
|
2216
2216
|
|
|
2217
2217
|
self.notin('pulls', dst_tree)
|
|
2218
2218
|
self.notin('pushs', dst_tree)
|
|
2219
|
+
|
|
2220
|
+
async def test_layer_readahead(self):
|
|
2221
|
+
|
|
2222
|
+
async with self.getTestCore() as core:
|
|
2223
|
+
|
|
2224
|
+
layr = core.getLayer()
|
|
2225
|
+
self.true(layr.layrslab.readahead)
|
|
2226
|
+
self.true(layr.layrslab.lenv.flags()['readahead'])
|
|
2227
|
+
self.false(layr.nodeeditslab.readahead)
|
|
2228
|
+
self.false(layr.nodeeditslab.lenv.flags()['readahead'])
|
|
2229
|
+
self.false(layr.dataslab.readahead)
|
|
2230
|
+
self.false(layr.dataslab.lenv.flags()['readahead'])
|
|
2231
|
+
|
|
2232
|
+
with self.setTstEnvars(SYNDEV_CORTEX_LAYER_READAHEAD='false'):
|
|
2233
|
+
iden = await core.callStorm('return($lib.layer.add().iden)')
|
|
2234
|
+
layr = core.getLayer(iden)
|
|
2235
|
+
self.false(layr.layrslab.readahead)
|
|
2236
|
+
self.false(layr.layrslab.lenv.flags()['readahead'])
|
|
2237
|
+
self.false(layr.nodeeditslab.readahead)
|
|
2238
|
+
self.false(layr.nodeeditslab.lenv.flags()['readahead'])
|
|
2239
|
+
self.false(layr.dataslab.readahead)
|
|
2240
|
+
self.false(layr.dataslab.lenv.flags()['readahead'])
|
|
@@ -559,3 +559,10 @@ class ModelRevTest(s_tests.SynTest):
|
|
|
559
559
|
self.len(2, rnodes)
|
|
560
560
|
|
|
561
561
|
self.eq([node.ndef[0] for node in nodes], [node.ndef[0] for node in reversed(rnodes)])
|
|
562
|
+
|
|
563
|
+
async def test_modelrev_0_2_27(self):
|
|
564
|
+
|
|
565
|
+
async with self.getRegrCore('model-0.2.27') as core:
|
|
566
|
+
nodes = await core.nodes('it:dev:repo:commit:id=" Foo "')
|
|
567
|
+
self.len(1, nodes)
|
|
568
|
+
self.eq('Foo', nodes[0].get('id'))
|
synapse/tests/test_lib_node.py
CHANGED
|
@@ -243,7 +243,8 @@ class NodeTest(s_t_utils.SynTest):
|
|
|
243
243
|
nodepaths = await alist(node.storm(runt, '-> test:int [:loc=$foo]', opts={'vars': {'foo': 'us'}}))
|
|
244
244
|
self.eq(nodepaths[0][0].props.get('loc'), 'us')
|
|
245
245
|
|
|
246
|
-
|
|
246
|
+
link = {'type': 'runtime'}
|
|
247
|
+
path = nodepaths[0][1].fork(node, link) # type: s_node.Path
|
|
247
248
|
path.vars['zed'] = 'ca'
|
|
248
249
|
|
|
249
250
|
# Path present, opts not present
|
|
@@ -251,12 +252,18 @@ class NodeTest(s_t_utils.SynTest):
|
|
|
251
252
|
self.eq(nodes[0][0].props.get('loc'), 'ca')
|
|
252
253
|
# path is not updated due to frame scope
|
|
253
254
|
self.none(path.vars.get('bar'), 'us')
|
|
255
|
+
self.len(2, path.links)
|
|
256
|
+
self.eq({'type': 'prop', 'prop': 'hehe'}, path.links[0][1])
|
|
257
|
+
self.eq(link, path.links[1][1])
|
|
254
258
|
|
|
255
259
|
# Path present, opts present but no opts['vars']
|
|
256
260
|
nodes = await alist(node.storm(runt, '-> test:int [:loc=$zed] $bar=$foo', opts={}, path=path))
|
|
257
261
|
self.eq(nodes[0][0].props.get('loc'), 'ca')
|
|
258
262
|
# path is not updated due to frame scope
|
|
259
263
|
self.none(path.vars.get('bar'))
|
|
264
|
+
self.len(2, path.links)
|
|
265
|
+
self.eq({'type': 'prop', 'prop': 'hehe'}, path.links[0][1])
|
|
266
|
+
self.eq(link, path.links[1][1])
|
|
260
267
|
|
|
261
268
|
# Path present, opts present with vars
|
|
262
269
|
nodes = await alist(node.storm(runt, '-> test:int [:loc=$zed] $bar=$baz',
|
|
@@ -294,6 +301,10 @@ class NodeTest(s_t_utils.SynTest):
|
|
|
294
301
|
self.eq(len(pcln.nodes), len(path.nodes))
|
|
295
302
|
pcln.nodes.pop(-1)
|
|
296
303
|
self.ne(len(pcln.nodes), len(path.nodes))
|
|
304
|
+
# Ensure the link elements are independent
|
|
305
|
+
pcln.links.append({'type': 'edge', 'verb': 'seen'})
|
|
306
|
+
self.len(3, pcln.links)
|
|
307
|
+
self.len(2, path.links)
|
|
297
308
|
|
|
298
309
|
# push a frame and clone it - ensure clone mods do not
|
|
299
310
|
# modify the original path
|
synapse/tests/test_lib_storm.py
CHANGED
|
@@ -3059,12 +3059,29 @@ class StormTest(s_t_utils.SynTest):
|
|
|
3059
3059
|
self.len(4, nodes)
|
|
3060
3060
|
|
|
3061
3061
|
q = 'inet:ipv4=1.2.3.4 | tee --join { -> * } { <- * }'
|
|
3062
|
-
|
|
3062
|
+
msgs = await core.stormlist(q, opts={'links': True})
|
|
3063
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
3063
3064
|
self.len(4, nodes)
|
|
3064
|
-
|
|
3065
|
-
self.eq(nodes[
|
|
3066
|
-
|
|
3067
|
-
self.
|
|
3065
|
+
|
|
3066
|
+
self.eq(nodes[0][0], ('inet:asn', 0))
|
|
3067
|
+
links = nodes[0][1]['links']
|
|
3068
|
+
self.len(1, links)
|
|
3069
|
+
self.eq({'type': 'prop', 'prop': 'asn'}, links[0][1])
|
|
3070
|
+
|
|
3071
|
+
self.eq(nodes[1][0][0], ('inet:dns:a'))
|
|
3072
|
+
links = nodes[1][1]['links']
|
|
3073
|
+
self.len(1, links)
|
|
3074
|
+
self.eq({'type': 'prop', 'prop': 'ipv4', 'reverse': True}, links[0][1])
|
|
3075
|
+
|
|
3076
|
+
self.eq(nodes[2][0][0], ('edge:refs'))
|
|
3077
|
+
links = nodes[2][1]['links']
|
|
3078
|
+
self.len(1, links)
|
|
3079
|
+
self.eq({'type': 'prop', 'prop': 'n2', 'reverse': True}, links[0][1])
|
|
3080
|
+
|
|
3081
|
+
self.eq(nodes[3][0], ('inet:ipv4', 0x01020304))
|
|
3082
|
+
links = nodes[2][1]['links']
|
|
3083
|
+
self.len(1, links)
|
|
3084
|
+
self.eq({'type': 'prop', 'prop': 'n2', 'reverse': True}, links[0][1])
|
|
3068
3085
|
|
|
3069
3086
|
q = 'inet:ipv4=1.2.3.4 | tee --join { -> * } { <- * } { -> edge:refs:n2 :n1 -> * }'
|
|
3070
3087
|
nodes = await core.nodes(q)
|
|
@@ -3834,10 +3851,18 @@ class StormTest(s_t_utils.SynTest):
|
|
|
3834
3851
|
self.eq(sorted([n.ndef[1] for n in nodes]), ['test1', 'test2'])
|
|
3835
3852
|
|
|
3836
3853
|
q = '[(test:str=refs) (test:str=foo)] $v=$node.value() | lift.byverb $v'
|
|
3837
|
-
|
|
3854
|
+
msgs = await core.stormlist(q, opts={'links': True})
|
|
3855
|
+
nodes = [n[1] for n in msgs if n[0] == 'node']
|
|
3838
3856
|
self.len(4, nodes)
|
|
3839
|
-
self.eq({n
|
|
3857
|
+
self.eq({n[0][1] for n in nodes},
|
|
3840
3858
|
{'test1', 'test2', 'refs', 'foo'})
|
|
3859
|
+
links = nodes[1][1]['links']
|
|
3860
|
+
self.len(1, links)
|
|
3861
|
+
self.eq({'type': 'runtime'}, links[0][1])
|
|
3862
|
+
|
|
3863
|
+
links = nodes[2][1]['links']
|
|
3864
|
+
self.len(1, links)
|
|
3865
|
+
self.eq({'type': 'runtime'}, links[0][1])
|
|
3841
3866
|
|
|
3842
3867
|
async def test_storm_nested_root(self):
|
|
3843
3868
|
async with self.getTestCore() as core:
|