synapse 2.168.0__py311-none-any.whl → 2.170.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.

Files changed (42) hide show
  1. synapse/cortex.py +99 -10
  2. synapse/datamodel.py +5 -0
  3. synapse/lib/agenda.py +3 -0
  4. synapse/lib/ast.py +70 -12
  5. synapse/lib/cell.py +83 -21
  6. synapse/lib/httpapi.py +3 -0
  7. synapse/lib/layer.py +75 -6
  8. synapse/lib/node.py +7 -0
  9. synapse/lib/snap.py +25 -5
  10. synapse/lib/storm.py +1 -1
  11. synapse/lib/stormlib/cortex.py +1 -1
  12. synapse/lib/stormlib/model.py +420 -1
  13. synapse/lib/stormtypes.py +68 -3
  14. synapse/lib/types.py +35 -0
  15. synapse/lib/version.py +2 -2
  16. synapse/lib/view.py +94 -24
  17. synapse/models/files.py +40 -0
  18. synapse/models/inet.py +8 -4
  19. synapse/models/infotech.py +355 -17
  20. synapse/tests/files/cpedata.json +525034 -0
  21. synapse/tests/test_cortex.py +99 -0
  22. synapse/tests/test_lib_agenda.py +17 -3
  23. synapse/tests/test_lib_ast.py +66 -0
  24. synapse/tests/test_lib_cell.py +133 -52
  25. synapse/tests/test_lib_layer.py +52 -1
  26. synapse/tests/test_lib_scrape.py +72 -71
  27. synapse/tests/test_lib_snap.py +16 -1
  28. synapse/tests/test_lib_storm.py +118 -0
  29. synapse/tests/test_lib_stormlib_cortex.py +27 -0
  30. synapse/tests/test_lib_stormlib_model.py +532 -0
  31. synapse/tests/test_lib_stormtypes.py +161 -14
  32. synapse/tests/test_lib_types.py +20 -0
  33. synapse/tests/test_lib_view.py +77 -0
  34. synapse/tests/test_model_files.py +51 -0
  35. synapse/tests/test_model_inet.py +63 -1
  36. synapse/tests/test_model_infotech.py +187 -26
  37. synapse/tests/utils.py +12 -0
  38. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/METADATA +1 -1
  39. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/RECORD +42 -41
  40. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/LICENSE +0 -0
  41. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/WHEEL +0 -0
  42. {synapse-2.168.0.dist-info → synapse-2.170.0.dist-info}/top_level.txt +0 -0
@@ -2430,6 +2430,41 @@ class CortexTest(s_t_utils.SynTest):
2430
2430
  msgs = await core.stormlist('test:int :loc -> test:newp')
2431
2431
  self.stormIsInErr('No property named test:newp', msgs)
2432
2432
 
2433
+ # ndef pivots
2434
+ await core.nodes('''
2435
+ [
2436
+ ( test:str=ndefpivdst )
2437
+ ( test:str=ndefpivsrc :bar=(test:str, ndefpivdst) )
2438
+ ( test:str=ndefpivprp :bar=(test:str, ndefpivdst) )
2439
+ ]
2440
+ ''')
2441
+
2442
+ nodes = await core.nodes('test:str=ndefpivsrc -> test:str')
2443
+ self.eq(['ndefpivdst'], [n.ndef[1] for n in nodes])
2444
+
2445
+ nodes = await core.nodes('test:str=ndefpivsrc -> test:str:bar')
2446
+ self.len(0, nodes)
2447
+
2448
+ nodes = await core.nodes('test:str=ndefpivdst -> test:str:bar')
2449
+ self.sorteq(['ndefpivprp', 'ndefpivsrc'], [n.ndef[1] for n in nodes])
2450
+
2451
+ nodes = await core.nodes('test:str=ndefpivsrc :bar -> * +test:str')
2452
+ self.eq(['ndefpivdst'], [n.ndef[1] for n in nodes])
2453
+
2454
+ nodes = await core.nodes('test:str=ndefpivsrc :bar -> test:str:bar')
2455
+ self.sorteq(['ndefpivprp', 'ndefpivsrc'], [n.ndef[1] for n in nodes])
2456
+
2457
+ nodes = await core.nodes('test:str=ndefpivsrc :bar -> test:str')
2458
+ self.eq(['ndefpivdst'], [n.ndef[1] for n in nodes])
2459
+
2460
+ nodes = await core.nodes('test:str=ndefpivsrc :bar -> test:int')
2461
+ self.len(0, nodes)
2462
+
2463
+ await core.nodes('test:str=ndefpivdst delnode')
2464
+ msgs = await core.stormlist('test:str=ndefpivsrc :bar -> test:str')
2465
+ self.len(0, [m for m in msgs if m[0] == 'node'])
2466
+ self.stormIsInWarn("Missing node corresponding to ndef ('test:str', 'ndefpivdst')", msgs)
2467
+
2433
2468
  # Bad pivot syntax go here
2434
2469
  for q in ['test:pivcomp :lulz <- *',
2435
2470
  'test:pivcomp :lulz <+- *',
@@ -6257,12 +6292,14 @@ class CortexBasicTest(s_t_utils.SynTest):
6257
6292
 
6258
6293
  # Can't delete the default view
6259
6294
  await self.asyncraises(s_exc.SynErr, core.delView(core.view.iden))
6295
+ await self.asyncraises(s_exc.SynErr, core._delViewWithLayer(core.view.iden, None, None))
6260
6296
 
6261
6297
  # Can't delete a layer in a view
6262
6298
  await self.asyncraises(s_exc.SynErr, core.delLayer(core.view.layers[0].iden))
6263
6299
 
6264
6300
  # Can't delete a nonexistent view
6265
6301
  await self.asyncraises(s_exc.NoSuchView, core.delView('XXX'))
6302
+ await self.asyncraises(s_exc.NoSuchView, core.delViewWithLayer('XXX'))
6266
6303
 
6267
6304
  # Can't delete a nonexistent layer
6268
6305
  await self.asyncraises(s_exc.NoSuchLayer, core.delLayer('XXX'))
@@ -6275,6 +6312,68 @@ class CortexBasicTest(s_t_utils.SynTest):
6275
6312
  await core.delView(view2_iden)
6276
6313
  await self.asyncraises(s_exc.NoSuchView, core.delView(view2_iden))
6277
6314
 
6315
+ layr = await core.addLayer()
6316
+ layriden = layr['iden']
6317
+ vdef3 = {'layers': (layriden,)}
6318
+ view3_iden = (await core.addView(vdef3)).get('iden')
6319
+
6320
+ opts = {'view': view3_iden}
6321
+ await core.callStorm('$lib.view.get().set(protected, $lib.true)', opts=opts)
6322
+
6323
+ await self.asyncraises(s_exc.CantDelView, core.delViewWithLayer(view3_iden))
6324
+
6325
+ await core.callStorm('$lib.view.get().set(protected, $lib.false)', opts=opts)
6326
+
6327
+ view3 = core.getView(view3_iden)
6328
+ vdef4 = await view3.fork()
6329
+
6330
+ deadlayr = view3.layers[0].iden
6331
+ view4_iden = vdef4.get('iden')
6332
+ view4 = core.getView(view4_iden)
6333
+
6334
+ self.eq(view4.parent, view3)
6335
+ self.len(2, view4.layers)
6336
+
6337
+ await core.auth.rootuser.setPasswd('secret')
6338
+ host, port = await core.dmon.listen('tcp://127.0.0.1:0/')
6339
+ layr2 = await core.callStorm('$layer=$lib.layer.add() return($layer)')
6340
+ varz = {'iden': layriden, 'tgt': layr2.get('iden'), 'port': port}
6341
+ opts = {'vars': varz, 'view': view3_iden}
6342
+
6343
+ pullq = '$layer=$lib.layer.get($iden).addPull(`tcp://root:secret@127.0.0.1:{$port}/*/layer/{$tgt}`)'
6344
+ pushq = '$layer=$lib.layer.get($iden).addPush(`tcp://root:secret@127.0.0.1:{$port}/*/layer/{$tgt}`)'
6345
+ msgs = await core.stormlist(pullq, opts=opts)
6346
+ self.stormHasNoWarnErr(msgs)
6347
+
6348
+ msgs = await core.stormlist(pushq, opts=opts)
6349
+ self.stormHasNoWarnErr(msgs)
6350
+
6351
+ coros = len(core.activecoros)
6352
+
6353
+ await core.delViewWithLayer(view3_iden)
6354
+
6355
+ # push/pull activecoros have been deleted
6356
+ self.len(coros - 2, core.activecoros)
6357
+
6358
+ self.none(view4.parent)
6359
+ self.len(1, view4.layers)
6360
+ self.none(core.getLayer(deadlayr))
6361
+
6362
+ vdef5 = await view4.fork()
6363
+ view5 = core.getView(vdef5.get('iden'))
6364
+
6365
+ usedlayr = view4.layers[0].iden
6366
+ vdef6 = {'layers': (usedlayr,)}
6367
+ view6 = core.getView((await core.addView(vdef6)).get('iden'))
6368
+
6369
+ await core.delViewWithLayer(view4_iden)
6370
+
6371
+ self.none(view5.parent)
6372
+ self.len(1, view5.layers)
6373
+
6374
+ self.nn(core.getLayer(usedlayr))
6375
+ self.eq([usedlayr], [lyr.iden for lyr in view6.layers])
6376
+
6278
6377
  async def test_cortex_view_opts(self):
6279
6378
  '''
6280
6379
  Test that the view opts work
@@ -1,3 +1,4 @@
1
+ import json
1
2
  import asyncio
2
3
  import hashlib
3
4
  import datetime
@@ -156,7 +157,7 @@ class AgendaTest(s_t_utils.SynTest):
156
157
  newts = ar.nexttime(now)
157
158
  self.eq(newts, datetime.datetime(year=2018, month=12, day=5, hour=7, minute=2, tzinfo=tz.utc).timestamp())
158
159
 
159
- async def test_agenda(self):
160
+ async def test_agenda_base(self):
160
161
  MONO_DELT = 1543827303.0
161
162
  unixtime = datetime.datetime(year=2018, month=12, day=5, hour=7, minute=0, tzinfo=tz.utc).timestamp()
162
163
 
@@ -382,8 +383,21 @@ class AgendaTest(s_t_utils.SynTest):
382
383
  self.true(appt.enabled)
383
384
  self.eq(0, appt.startcount)
384
385
 
385
- unixtime = datetime.datetime(year=2019, month=2, day=13, hour=10, minute=16, tzinfo=tz.utc).timestamp()
386
- self.eq((12, 'bar'), await asyncio.wait_for(core.callStorm('return($lib.queue.gen(visi).pop(wait=$lib.true))'), timeout=5))
386
+ # Ensure structured logging captures the cron iden value
387
+ core.stormlog = True
388
+ with self.getStructuredAsyncLoggerStream('synapse.storm') as stream:
389
+ unixtime = datetime.datetime(year=2019, month=2, day=13, hour=10, minute=16,
390
+ tzinfo=tz.utc).timestamp()
391
+ self.eq((12, 'bar'), await asyncio.wait_for(core.callStorm('return($lib.queue.gen(visi).pop(wait=$lib.true))'), timeout=5))
392
+ core.stormlog = False
393
+
394
+ data = stream.getvalue()
395
+ raw_mesgs = [m for m in data.split('\n') if m]
396
+ msgs = [json.loads(m) for m in raw_mesgs]
397
+ msgs = [m for m in msgs if m['text'] == '$lib.queue.gen(visi).put(bar)']
398
+ self.gt(len(msgs), 0)
399
+ for m in msgs:
400
+ self.eq(m.get('cron'), appt.iden)
387
401
 
388
402
  self.eq(1, appt.startcount)
389
403
 
@@ -670,6 +670,28 @@ class AstTest(s_test.SynTest):
670
670
  self.len(1, nodes)
671
671
  self.eq('geo:nloc', nodes[0].ndef[0])
672
672
 
673
+ await core.nodes('[ test:str=ndefs :ndefs=((it:dev:int, 1), (it:dev:int, 2)) ]')
674
+ await core.nodes('test:str=ndefs [ :ndefs += (inet:fqdn, woot.com) ]')
675
+ self.len(1, nodes)
676
+
677
+ nodes = await core.nodes('it:dev:int=1 -> test:str:ndefs')
678
+ self.len(1, nodes)
679
+ self.eq('ndefs', nodes[0].ndef[1])
680
+ self.eq(nodes[0].getNodeRefs(), [
681
+ ('ndefs', ('it:dev:int', 1)),
682
+ ('ndefs', ('it:dev:int', 2)),
683
+ ('ndefs', ('inet:fqdn', 'woot.com'))
684
+ ])
685
+
686
+ nodes = await core.nodes('[ test:str = norefs ]')
687
+ self.eq(nodes[0].getNodeRefs(), [])
688
+
689
+ self.len(1, await core.nodes('it:dev:int=1 -> test:str'))
690
+ self.len(3, await core.nodes('test:str=ndefs -> *'))
691
+ self.len(2, await core.nodes('test:str=ndefs -> it:dev:int'))
692
+ self.len(3, await core.nodes('test:str=ndefs :ndefs -> *'))
693
+ self.len(2, await core.nodes('test:str=ndefs :ndefs -> it:dev:int'))
694
+
673
695
  async def test_ast_pivot(self):
674
696
  # a general purpose pivot test. come on in!
675
697
  async with self.getTestCore() as core:
@@ -2761,6 +2783,50 @@ class AstTest(s_test.SynTest):
2761
2783
  self.stormHasNoWarnErr(msgs)
2762
2784
  self.len(0, calls)
2763
2785
 
2786
+ async def test_ast_tag_optimization(self):
2787
+ calls = []
2788
+ origtag = s_snap.Snap.nodesByTag
2789
+
2790
+ async def checkTag(self, tag, form=None, reverse=False):
2791
+ calls.append(('tag', tag, form))
2792
+ async for node in origtag(self, tag, form=form, reverse=reverse):
2793
+ yield node
2794
+
2795
+ with mock.patch('synapse.lib.snap.Snap.nodesByTag', checkTag):
2796
+ async with self.getTestCore() as core:
2797
+ self.len(1, await core.nodes('[inet:asn=200 :name=visi]'))
2798
+ self.len(1, await core.nodes('[test:int=12 +#visi]'))
2799
+ self.len(1, await core.nodes('[test:int=99 +#visi]'))
2800
+
2801
+ nodes = await core.nodes('test:int +#$x', opts={'vars': {'x': 'visi'}})
2802
+ self.len(2, nodes)
2803
+ self.len(1, calls)
2804
+ self.eq(('tag', 'visi', 'test:int'), calls[0])
2805
+
2806
+ calls = []
2807
+ # not for non-runtsafe
2808
+ nodes = await core.nodes('inet:asn:name $valu=:name test:int +#$valu')
2809
+ self.len(2, nodes)
2810
+ self.len(0, calls)
2811
+
2812
+ nodes = await core.nodes('''
2813
+ $tag = 'yeyeyeyeyeyeyeyeye'
2814
+ if $x {
2815
+ $tag = 'visi'
2816
+ } else {
2817
+ $tag = 'lolnope'
2818
+ }
2819
+ test:int +#$tag
2820
+ ''', opts={'vars': {'x': True}})
2821
+ self.len(2, nodes)
2822
+ self.len(1, calls)
2823
+ self.eq(('tag', 'visi', 'test:int'), calls[0])
2824
+
2825
+ calls = []
2826
+ nodes = await core.nodes('test:int +#$x', opts={'vars': {'x': 'v*'}})
2827
+ self.len(2, nodes)
2828
+ self.len(0, calls)
2829
+
2764
2830
  async def test_ast_cmdoper(self):
2765
2831
 
2766
2832
  async with self.getTestCore() as core:
@@ -1,6 +1,7 @@
1
1
  import os
2
2
  import ssl
3
3
  import sys
4
+ import json
4
5
  import time
5
6
  import base64
6
7
  import signal
@@ -33,6 +34,7 @@ import synapse.lib.version as s_version
33
34
  import synapse.lib.hiveauth as s_hiveauth
34
35
  import synapse.lib.lmdbslab as s_lmdbslab
35
36
  import synapse.lib.crypto.passwd as s_passwd
37
+ import synapse.lib.platforms.linux as s_linux
36
38
 
37
39
  import synapse.tools.backup as s_tools_backup
38
40
 
@@ -496,52 +498,6 @@ class CellTest(s_t_utils.SynTest):
496
498
  with self.raises(s_exc.AuthDeny):
497
499
  await prox.setCellUser(visiiden)
498
500
 
499
- async def test_cell_hiveboot(self):
500
-
501
- with self.getTestDir() as dirn:
502
-
503
- tree = {
504
- 'kids': {
505
- 'hehe': {'value': 'haha'},
506
- }
507
- }
508
-
509
- bootpath = os.path.join(dirn, 'hiveboot.yaml')
510
-
511
- s_common.yamlsave(tree, bootpath)
512
-
513
- with warnings.catch_warnings(record=True) as warns:
514
- async with self.getTestCell(s_cell.Cell, dirn=dirn) as cell:
515
- self.eq('haha', await cell.hive.get(('hehe',)))
516
-
517
- self.isin('Initial hive config from hiveboot.yaml', str(warns[0].message))
518
-
519
- # test that the file does not load again
520
- tree['kids']['redballoons'] = {'value': 99}
521
- s_common.yamlsave(tree, bootpath)
522
-
523
- async with self.getTestCell(s_cell.Cell, dirn=dirn) as cell:
524
- self.none(await cell.hive.get(('redballoons',)))
525
-
526
- # Do a full hive dump/load
527
- with self.getTestDir() as dirn:
528
- dir0 = s_common.genpath(dirn, 'cell00')
529
- dir1 = s_common.genpath(dirn, 'cell01')
530
- async with self.getTestCell(s_cell.Cell, dirn=dir0, conf={'auth:passwd': 'root'}) as cell00:
531
- await cell00.hive.set(('beeps',), [1, 2, 'three'])
532
-
533
- tree = await cell00.saveHiveTree()
534
- s_common.yamlsave(tree, dir1, 'hiveboot.yaml')
535
- with s_common.genfile(dir1, 'cell.guid') as fd:
536
- _ = fd.write(cell00.iden.encode())
537
-
538
- async with self.getTestCell(s_cell.Cell, dirn=dir1) as cell01:
539
- resp = await cell01.hive.get(('beeps',))
540
- self.isinstance(resp, tuple)
541
- self.eq(resp, (1, 2, 'three'))
542
-
543
- self.eq(cell00.iden, cell01.iden)
544
-
545
501
  async def test_cell_getinfo(self):
546
502
  async with self.getTestCore() as cell:
547
503
  cell.COMMIT = 'mycommit'
@@ -2243,8 +2199,8 @@ class CellTest(s_t_utils.SynTest):
2243
2199
  async with self.getTestCore(dirn=dirn, conf=conf) as core:
2244
2200
  pass
2245
2201
 
2246
- stream.seek(0)
2247
- self.isin('onboot optimization complete!', stream.read())
2202
+ stream.seek(0)
2203
+ self.isin('onboot optimization complete!', stream.read())
2248
2204
 
2249
2205
  stat01 = os.stat(lmdbfile)
2250
2206
  self.ne(stat00.st_ino, stat01.st_ino)
@@ -2266,10 +2222,25 @@ class CellTest(s_t_utils.SynTest):
2266
2222
  async with self.getTestCore(dirn=dirn, conf=conf) as core:
2267
2223
  pass
2268
2224
 
2269
- stream.seek(0)
2270
- buf = stream.read()
2271
- self.notin('onboot optimization complete!', buf)
2272
- self.isin('not on the same volume', buf)
2225
+ stream.seek(0)
2226
+ buf = stream.read()
2227
+ self.notin('onboot optimization complete!', buf)
2228
+ self.isin('not on the same volume', buf)
2229
+
2230
+ # Local backup files are skipped
2231
+ async with self.getTestCore(dirn=dirn) as core:
2232
+ await core.runBackup()
2233
+
2234
+ with self.getAsyncLoggerStream('synapse.lib.cell') as stream:
2235
+
2236
+ conf = {'onboot:optimize': True}
2237
+ async with self.getTestCore(dirn=dirn, conf=conf) as core:
2238
+ pass
2239
+
2240
+ stream.seek(0)
2241
+ buf = stream.read()
2242
+ self.isin('Skipping backup file', buf)
2243
+ self.isin('onboot optimization complete!', buf)
2273
2244
 
2274
2245
  async def test_cell_gc(self):
2275
2246
  async with self.getTestCore() as core:
@@ -2642,3 +2613,113 @@ class CellTest(s_t_utils.SynTest):
2642
2613
 
2643
2614
  with self.raises(s_exc.NoSuchIden):
2644
2615
  await cell.delUserApiKey(newp)
2616
+
2617
+ async def test_cell_check_sysctl(self):
2618
+ sysctls = s_linux.getSysctls()
2619
+
2620
+ sysvals = s_cell.Cell.SYSCTL_VALS.copy()
2621
+ sysvals['vm.dirty_expire_centisecs'] += 1
2622
+ sysvals['vm.dirty_writeback_centisecs'] += 1
2623
+
2624
+ # Detect and report incorrect values
2625
+ with self.getStructuredAsyncLoggerStream('synapse.lib.cell') as stream:
2626
+ with mock.patch.object(s_cell.Cell, 'SYSCTL_VALS', sysvals):
2627
+ async with self.getTestCore():
2628
+ pass
2629
+
2630
+ stream.seek(0)
2631
+ data = stream.getvalue()
2632
+ raw_mesgs = [m for m in data.split('\\n') if m]
2633
+ msgs = [json.loads(m) for m in raw_mesgs]
2634
+
2635
+ self.len(1, msgs)
2636
+
2637
+ mesg = f'Sysctl values different than expected: {", ".join(sysvals)}. '
2638
+ mesg += 'See https://synapse.docs.vertex.link/en/latest/synapse/devopsguide.html#performance-tuning '
2639
+ mesg += 'for information about these sysctl parameters.'
2640
+ self.eq(msgs[0]['message'], mesg)
2641
+ self.eq(msgs[0]['sysctls'], [
2642
+ {'name': 'vm.dirty_expire_centisecs', 'expected': 21, 'actual': sysctls['vm.dirty_expire_centisecs']},
2643
+ {'name': 'vm.dirty_writeback_centisecs', 'expected': 21, 'actual': sysctls['vm.dirty_writeback_centisecs']},
2644
+ ])
2645
+
2646
+ # Copy the current sysctl valus to the cell so the check passes
2647
+ sysvals = {
2648
+ 'vm.dirty_expire_centisecs': sysctls['vm.dirty_expire_centisecs'],
2649
+ 'vm.dirty_writeback_centisecs': sysctls['vm.dirty_writeback_centisecs'],
2650
+ }
2651
+
2652
+ # Detect correct values and stop the task
2653
+ with self.getLoggerStream('synapse.lib.cell') as stream:
2654
+ with mock.patch.object(s_cell.Cell, 'SYSCTL_VALS', sysvals):
2655
+ async with self.getTestCore():
2656
+ pass
2657
+
2658
+ stream.seek(0)
2659
+ data = stream.read()
2660
+ self.len(0, data)
2661
+
2662
+ # Disable the sysctl check and don't check at all
2663
+ with self.getLoggerStream('synapse.lib.cell') as stream:
2664
+ conf = {'health:sysctl:checks': False}
2665
+ async with self.getTestCore(conf=conf):
2666
+ pass
2667
+
2668
+ stream.seek(0)
2669
+ data = stream.read()
2670
+ self.len(0, data, msg=data)
2671
+
2672
+ async def test_cell_version_regression(self):
2673
+ oldver = (0, 1, 0)
2674
+ newver = (0, 2, 0)
2675
+
2676
+ class TestCell(s_cell.Cell):
2677
+ VERSION = newver
2678
+
2679
+ with self.getTestDir() as dirn:
2680
+ async with self.getTestCell(TestCell, dirn=dirn):
2681
+ pass
2682
+
2683
+ with self.raises(s_exc.BadVersion) as exc:
2684
+ with mock.patch.object(TestCell, 'VERSION', oldver):
2685
+ with self.getLoggerStream('synapse.lib.cell') as stream:
2686
+ async with self.getTestCell(TestCell, dirn=dirn):
2687
+ pass
2688
+
2689
+ mesg = f'Cell version regression (testcell) is not allowed! Stored version: {newver}, current version: {oldver}.'
2690
+ self.eq(exc.exception.get('mesg'), mesg)
2691
+ self.eq(exc.exception.get('currver'), oldver)
2692
+ self.eq(exc.exception.get('lastver'), newver)
2693
+
2694
+ stream.seek(0)
2695
+ data = stream.read()
2696
+ self.isin(mesg, data)
2697
+
2698
+ async with self.getTestCell(TestCell, dirn=dirn):
2699
+ pass
2700
+
2701
+ with self.getTestDir() as dirn:
2702
+ async with self.getTestCell(s_cell.Cell, dirn=dirn):
2703
+ pass
2704
+
2705
+ synver = list(s_version.version)
2706
+ synver[1] -= 1
2707
+ synver = tuple(synver)
2708
+
2709
+ with self.raises(s_exc.BadVersion) as exc:
2710
+ with mock.patch.object(s_version, 'version', synver):
2711
+ with self.getLoggerStream('synapse.lib.cell') as stream:
2712
+ async with self.getTestCell(s_cell.Cell, dirn=dirn):
2713
+ pass
2714
+
2715
+ mesg = f'Synapse version regression (cell) is not allowed! Stored version: {s_version.version}, current version: {synver}.'
2716
+ self.eq(exc.exception.get('mesg'), mesg)
2717
+ self.eq(exc.exception.get('currver'), synver)
2718
+ self.eq(exc.exception.get('lastver'), s_version.version)
2719
+
2720
+ stream.seek(0)
2721
+ data = stream.read()
2722
+ self.isin(mesg, data)
2723
+
2724
+ async with self.getTestCell(s_cell.Cell, dirn=dirn):
2725
+ pass
@@ -26,7 +26,7 @@ class LayerTest(s_t_utils.SynTest):
26
26
 
27
27
  def checkLayrvers(self, core):
28
28
  for layr in core.layers.values():
29
- self.eq(layr.layrvers, 10)
29
+ self.eq(layr.layrvers, 11)
30
30
 
31
31
  async def test_layer_verify(self):
32
32
 
@@ -1530,6 +1530,57 @@ class LayerTest(s_t_utils.SynTest):
1530
1530
  verbs = [verb async for verb in nodes0[0].iterEdgeVerbs(buid2)]
1531
1531
  self.len(0, verbs)
1532
1532
 
1533
+ async def test_layer_v11(self):
1534
+
1535
+ try:
1536
+
1537
+ oldv = s_layer.MIGR_COMMIT_SIZE
1538
+ s_layer.MIGR_COMMIT_SIZE = 1
1539
+
1540
+ async with self.getRegrCore('layer-v11') as core:
1541
+
1542
+ wlyrs_byview = await core.callStorm('''
1543
+ $wlyrs = ({})
1544
+ for $view in $lib.view.list() {
1545
+ $wlyrs.($view.get(name)) = $view.layers.0.iden
1546
+ }
1547
+ return($wlyrs)
1548
+ ''')
1549
+ self.len(8, wlyrs_byview)
1550
+
1551
+ layr = core.getLayer(iden=wlyrs_byview['default'])
1552
+ await self.agenlen(2, layr.getStorNodesByForm('test:str'))
1553
+ await self.agenlen(1, layr.getStorNodesByForm('syn:tag'))
1554
+
1555
+ layr = core.getLayer(iden=wlyrs_byview['prop'])
1556
+ await self.agenlen(1, layr.getStorNodesByForm('test:str'))
1557
+
1558
+ layr = core.getLayer(iden=wlyrs_byview['tags'])
1559
+ await self.agenlen(1, layr.getStorNodesByForm('test:str'))
1560
+ await self.agenlen(1, layr.getStorNodesByForm('syn:tag'))
1561
+
1562
+ layr = core.getLayer(iden=wlyrs_byview['tagp'])
1563
+ await self.agenlen(1, layr.getStorNodesByForm('test:str'))
1564
+ await self.agenlen(0, layr.getStorNodesByForm('syn:tag'))
1565
+
1566
+ layr = core.getLayer(iden=wlyrs_byview['n1eg'])
1567
+ await self.agenlen(1, layr.getStorNodesByForm('test:str'))
1568
+ await self.agenlen(1, layr.getStorNodesByForm('test:int'))
1569
+
1570
+ layr = core.getLayer(iden=wlyrs_byview['n2eg'])
1571
+ await self.agenlen(0, layr.getStorNodesByForm('test:str'))
1572
+ await self.agenlen(1, layr.getStorNodesByForm('test:int'))
1573
+
1574
+ layr = core.getLayer(iden=wlyrs_byview['data'])
1575
+ await self.agenlen(1, layr.getStorNodesByForm('test:str'))
1576
+
1577
+ layr = core.getLayer(iden=wlyrs_byview['noop'])
1578
+ await self.agenlen(0, layr.getStorNodes())
1579
+ await self.agenlen(0, layr.getStorNodesByForm('test:str'))
1580
+
1581
+ finally:
1582
+ s_layer.MIGR_COMMIT_SIZE = oldv
1583
+
1533
1584
  async def test_layer_logedits_default(self):
1534
1585
  async with self.getTestCore() as core:
1535
1586
  self.true(core.getLayer().logedits)