synapse 2.180.1__py311-none-any.whl → 2.181.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/assets/__init__.py +35 -0
- synapse/assets/storm/migrations/model-0.2.28.storm +355 -0
- synapse/common.py +2 -1
- synapse/cortex.py +49 -35
- synapse/cryotank.py +1 -1
- synapse/datamodel.py +30 -0
- synapse/lib/ast.py +12 -7
- synapse/lib/cell.py +1 -1
- synapse/lib/chop.py +0 -1
- synapse/lib/drive.py +8 -8
- synapse/lib/layer.py +55 -13
- synapse/lib/lmdbslab.py +26 -5
- synapse/lib/modelrev.py +28 -1
- synapse/lib/modules.py +1 -0
- synapse/lib/nexus.py +1 -1
- synapse/lib/node.py +5 -0
- synapse/lib/parser.py +23 -16
- synapse/lib/scrape.py +1 -1
- synapse/lib/slabseqn.py +2 -2
- synapse/lib/snap.py +129 -0
- synapse/lib/storm.lark +16 -2
- synapse/lib/storm.py +3 -0
- synapse/lib/storm_format.py +1 -0
- synapse/lib/stormhttp.py +34 -1
- synapse/lib/stormlib/auth.py +1 -1
- synapse/lib/stormlib/cortex.py +5 -2
- synapse/lib/stormlib/ipv6.py +2 -2
- synapse/lib/stormlib/model.py +114 -12
- synapse/lib/stormlib/project.py +1 -1
- synapse/lib/stormtypes.py +81 -7
- synapse/lib/types.py +7 -0
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +47 -0
- synapse/models/inet.py +10 -3
- synapse/models/infotech.py +2 -1
- synapse/models/language.py +4 -0
- synapse/models/math.py +50 -0
- synapse/models/orgs.py +8 -0
- synapse/models/risk.py +9 -0
- synapse/tests/files/stormcov/pragma-nocov.storm +18 -0
- synapse/tests/test_assets.py +25 -0
- synapse/tests/test_cortex.py +129 -0
- synapse/tests/test_datamodel.py +6 -0
- synapse/tests/test_lib_grammar.py +7 -1
- synapse/tests/test_lib_layer.py +35 -0
- synapse/tests/test_lib_lmdbslab.py +11 -9
- synapse/tests/test_lib_modelrev.py +655 -1
- synapse/tests/test_lib_slabseqn.py +5 -4
- synapse/tests/test_lib_snap.py +4 -0
- synapse/tests/test_lib_storm.py +72 -1
- synapse/tests/test_lib_stormhttp.py +99 -1
- synapse/tests/test_lib_stormlib_cortex.py +21 -4
- synapse/tests/test_lib_stormlib_iters.py +8 -5
- synapse/tests/test_lib_stormlib_model.py +45 -6
- synapse/tests/test_lib_stormtypes.py +158 -2
- synapse/tests/test_lib_types.py +6 -0
- synapse/tests/test_model_inet.py +10 -0
- synapse/tests/test_model_language.py +4 -0
- synapse/tests/test_model_math.py +22 -0
- synapse/tests/test_model_orgs.py +6 -2
- synapse/tests/test_model_risk.py +4 -0
- synapse/tests/test_utils_stormcov.py +5 -0
- synapse/tests/utils.py +18 -5
- synapse/utils/stormcov/plugin.py +31 -1
- synapse/vendor/cpython/LICENSE +279 -0
- synapse/vendor/cpython/__init__.py +0 -0
- synapse/vendor/cpython/lib/__init__.py +0 -0
- synapse/vendor/cpython/lib/email/__init__.py +0 -0
- synapse/vendor/cpython/lib/email/_parseaddr.py +560 -0
- synapse/vendor/cpython/lib/email/utils.py +505 -0
- synapse/vendor/cpython/lib/ipaddress.py +2366 -0
- synapse/vendor/cpython/lib/test/__init__.py +0 -0
- synapse/vendor/cpython/lib/test/support/__init__.py +114 -0
- synapse/vendor/cpython/lib/test/test_email/__init__.py +0 -0
- synapse/vendor/cpython/lib/test/test_email/test_email.py +480 -0
- synapse/vendor/cpython/lib/test/test_email/test_utils.py +167 -0
- synapse/vendor/cpython/lib/test/test_ipaddress.py +2672 -0
- synapse/vendor/utils.py +4 -3
- {synapse-2.180.1.dist-info → synapse-2.181.0.dist-info}/METADATA +1 -1
- {synapse-2.180.1.dist-info → synapse-2.181.0.dist-info}/RECORD +83 -66
- {synapse-2.180.1.dist-info → synapse-2.181.0.dist-info}/WHEEL +1 -1
- synapse/lib/jupyter.py +0 -505
- synapse/tests/test_lib_jupyter.py +0 -224
- {synapse-2.180.1.dist-info → synapse-2.181.0.dist-info}/LICENSE +0 -0
- {synapse-2.180.1.dist-info → synapse-2.181.0.dist-info}/top_level.txt +0 -0
synapse/lib/view.py
CHANGED
|
@@ -824,6 +824,53 @@ class View(s_nexus.Pusher): # type: ignore
|
|
|
824
824
|
|
|
825
825
|
return count
|
|
826
826
|
|
|
827
|
+
async def iterPropValues(self, propname):
|
|
828
|
+
prop = self.core.model.reqProp(propname)
|
|
829
|
+
|
|
830
|
+
formname = None
|
|
831
|
+
propname = None
|
|
832
|
+
|
|
833
|
+
if prop.isform:
|
|
834
|
+
formname = prop.name
|
|
835
|
+
else:
|
|
836
|
+
propname = prop.name
|
|
837
|
+
if not prop.isuniv:
|
|
838
|
+
formname = prop.form.name
|
|
839
|
+
|
|
840
|
+
async def wrapgenr(lidx, genr):
|
|
841
|
+
async for indx, valu in genr:
|
|
842
|
+
yield indx, valu, lidx
|
|
843
|
+
|
|
844
|
+
genrs = []
|
|
845
|
+
for lidx, layr in enumerate(self.layers):
|
|
846
|
+
genr = layr.iterPropValues(formname, propname, prop.type.stortype)
|
|
847
|
+
genrs.append(wrapgenr(lidx, genr))
|
|
848
|
+
|
|
849
|
+
lastvalu = None
|
|
850
|
+
async for indx, valu, lidx in s_common.merggenr2(genrs):
|
|
851
|
+
if valu == lastvalu:
|
|
852
|
+
continue
|
|
853
|
+
|
|
854
|
+
if lidx == 0 or propname is None:
|
|
855
|
+
lastvalu = valu
|
|
856
|
+
yield valu
|
|
857
|
+
else:
|
|
858
|
+
valid = False
|
|
859
|
+
async for buid in self.layers[lidx].iterPropIndxBuids(formname, propname, indx):
|
|
860
|
+
for layr in self.layers[0:lidx]:
|
|
861
|
+
if (sode := layr._getStorNode(buid)) is None:
|
|
862
|
+
continue
|
|
863
|
+
|
|
864
|
+
if sode['props'].get(propname) is not None:
|
|
865
|
+
break
|
|
866
|
+
else:
|
|
867
|
+
valid = True
|
|
868
|
+
|
|
869
|
+
if valid:
|
|
870
|
+
lastvalu = valu
|
|
871
|
+
yield valu
|
|
872
|
+
break
|
|
873
|
+
|
|
827
874
|
async def getEdgeVerbs(self):
|
|
828
875
|
|
|
829
876
|
async with await s_spooled.Set.anit(dirn=self.core.dirn, cell=self.core) as vset:
|
synapse/models/inet.py
CHANGED
|
@@ -2,8 +2,6 @@ import socket
|
|
|
2
2
|
import asyncio
|
|
3
3
|
import hashlib
|
|
4
4
|
import logging
|
|
5
|
-
import ipaddress
|
|
6
|
-
import email.utils
|
|
7
5
|
import urllib.parse
|
|
8
6
|
|
|
9
7
|
import idna
|
|
@@ -20,7 +18,12 @@ import synapse.lib.scrape as s_scrape
|
|
|
20
18
|
import synapse.lib.module as s_module
|
|
21
19
|
import synapse.lookup.iana as s_l_iana
|
|
22
20
|
|
|
21
|
+
import synapse.vendor.cpython.lib.email.utils as s_v_email_utils
|
|
22
|
+
|
|
23
23
|
logger = logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
ipaddress = s_common.ipaddress
|
|
26
|
+
|
|
24
27
|
drivre = regex.compile(r'^\w[:|]')
|
|
25
28
|
fqdnre = regex.compile(r'^[\w._-]+$', regex.U)
|
|
26
29
|
srv6re = regex.compile(r'^\[([a-f0-9\.:]+)\](?::(\d+))?$', regex.IGNORECASE)
|
|
@@ -811,13 +814,17 @@ class Rfc2822Addr(s_types.Str):
|
|
|
811
814
|
valu = ' '.join(valu.split())
|
|
812
815
|
|
|
813
816
|
try:
|
|
814
|
-
name, addr =
|
|
817
|
+
name, addr = s_v_email_utils.parseaddr(valu, strict=True)
|
|
815
818
|
except Exception as e: # pragma: no cover
|
|
816
819
|
# not sure we can ever really trigger this with a string as input
|
|
817
820
|
mesg = f'email.utils.parsaddr failed: {str(e)}'
|
|
818
821
|
raise s_exc.BadTypeValu(valu=valu, name=self.name,
|
|
819
822
|
mesg=mesg) from None
|
|
820
823
|
|
|
824
|
+
if not name and not addr:
|
|
825
|
+
raise s_exc.BadTypeValu(valu=valu, name=self.name,
|
|
826
|
+
mesg=f'No name or email parsed from {valu}')
|
|
827
|
+
|
|
821
828
|
subs = {}
|
|
822
829
|
if name:
|
|
823
830
|
subs['name'] = name
|
synapse/models/infotech.py
CHANGED
|
@@ -199,7 +199,6 @@ URI_PERCENT_CHARS = [
|
|
|
199
199
|
]
|
|
200
200
|
|
|
201
201
|
def uri_quote(text):
|
|
202
|
-
ret = ''
|
|
203
202
|
for (pct, char) in URI_PERCENT_CHARS:
|
|
204
203
|
text = text.replace(char, pct)
|
|
205
204
|
return text
|
|
@@ -1070,6 +1069,8 @@ class ItModule(s_module.CoreModule):
|
|
|
1070
1069
|
'doc': 'The snort rule is intended for use in detecting the target node.'}),
|
|
1071
1070
|
(('it:app:yara:rule', 'detects', None), {
|
|
1072
1071
|
'doc': 'The YARA rule is intended for use in detecting the target node.'}),
|
|
1072
|
+
(('it:dev:repo', 'has', 'inet:url'), {
|
|
1073
|
+
'doc': 'The repo has content hosted at the URL.'}),
|
|
1073
1074
|
),
|
|
1074
1075
|
'forms': (
|
|
1075
1076
|
('it:hostname', {}, ()),
|
synapse/models/language.py
CHANGED
|
@@ -12,6 +12,9 @@ class LangModule(s_module.CoreModule):
|
|
|
12
12
|
'deprecated': True,
|
|
13
13
|
'doc': 'Deprecated. Please use lang:translation.'}),
|
|
14
14
|
|
|
15
|
+
('lang:phrase', ('str', {'lower': True, 'onespace': True}), {
|
|
16
|
+
'doc': 'A small group of words which stand together as a concept.'}),
|
|
17
|
+
|
|
15
18
|
('lang:trans', ('str', {}), {
|
|
16
19
|
'deprecated': True,
|
|
17
20
|
'doc': 'Deprecated. Please use lang:translation.'}),
|
|
@@ -31,6 +34,7 @@ class LangModule(s_module.CoreModule):
|
|
|
31
34
|
),
|
|
32
35
|
'forms': (
|
|
33
36
|
|
|
37
|
+
('lang:phrase', {}, ()),
|
|
34
38
|
('lang:idiom', {}, (
|
|
35
39
|
|
|
36
40
|
('url', ('inet:url', {}), {
|
synapse/models/math.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import synapse.lib.module as s_module
|
|
2
|
+
|
|
3
|
+
class MathModule(s_module.CoreModule):
|
|
4
|
+
|
|
5
|
+
def getModelDefs(self):
|
|
6
|
+
return (('math', {
|
|
7
|
+
'types': (
|
|
8
|
+
|
|
9
|
+
('math:algorithm', ('guid', {}), {
|
|
10
|
+
'doc': 'A mathematical algorithm.'}),
|
|
11
|
+
|
|
12
|
+
('math:algorithm:type:taxonomy', ('taxonomy', {}), {
|
|
13
|
+
'interfaces': ('meta:taxonomy',),
|
|
14
|
+
'doc': 'A hierarchical taxonomy of algorithm types.'}),
|
|
15
|
+
),
|
|
16
|
+
'edges': (
|
|
17
|
+
|
|
18
|
+
(('risk:tool:software', 'uses', 'math:algorithm'), {
|
|
19
|
+
'doc': 'The tool uses the algorithm.'}),
|
|
20
|
+
|
|
21
|
+
(('it:prod:softver', 'uses', 'math:algorithm'), {
|
|
22
|
+
'doc': 'The software uses the algorithm.'}),
|
|
23
|
+
|
|
24
|
+
(('file:bytes', 'uses', 'math:algorithm'), {
|
|
25
|
+
'doc': 'The file uses the algorithm.'}),
|
|
26
|
+
|
|
27
|
+
(('math:algorithm', 'generates', None), {
|
|
28
|
+
'doc': 'The target node was generated by the algorithm.'}),
|
|
29
|
+
),
|
|
30
|
+
'forms': (
|
|
31
|
+
|
|
32
|
+
('math:algorithm:type:taxonomy', {}, ()),
|
|
33
|
+
|
|
34
|
+
('math:algorithm', {}, (
|
|
35
|
+
|
|
36
|
+
('name', ('str', {'lower': True, 'onespace': True}), {
|
|
37
|
+
'doc': 'The name of the algorithm.'}),
|
|
38
|
+
|
|
39
|
+
('type', ('math:algorithm:type:taxonomy', {}), {
|
|
40
|
+
'doc': 'The type of algorithm.'}),
|
|
41
|
+
|
|
42
|
+
('desc', ('str', {}), {
|
|
43
|
+
'disp': {'hint': 'text'},
|
|
44
|
+
'doc': 'A description of the algorithm.'}),
|
|
45
|
+
|
|
46
|
+
('created', ('time', {}), {
|
|
47
|
+
'doc': 'The time that the algorithm was authored.'}),
|
|
48
|
+
)),
|
|
49
|
+
),
|
|
50
|
+
}),)
|
synapse/models/orgs.py
CHANGED
|
@@ -480,6 +480,9 @@ class OuModule(s_module.CoreModule):
|
|
|
480
480
|
('goal', ('ou:goal', {}), {
|
|
481
481
|
'doc': 'The assessed primary goal of the campaign.'}),
|
|
482
482
|
|
|
483
|
+
('slogan', ('lang:phrase', {}), {
|
|
484
|
+
'doc': 'The slogan used by the campaign.'}),
|
|
485
|
+
|
|
483
486
|
('actors', ('array', {'type': 'ps:contact', 'split': ',', 'uniq': True, 'sorted': True}), {
|
|
484
487
|
'doc': 'Actors who participated in the campaign.'}),
|
|
485
488
|
|
|
@@ -633,12 +636,16 @@ class OuModule(s_module.CoreModule):
|
|
|
633
636
|
'doc': 'Location for an organization.'
|
|
634
637
|
}),
|
|
635
638
|
('name', ('ou:name', {}), {
|
|
639
|
+
'alts': ('names',),
|
|
636
640
|
'doc': 'The localized name of an organization.',
|
|
637
641
|
}),
|
|
638
642
|
('type', ('str', {'lower': True, 'strip': True}), {
|
|
639
643
|
'deprecated': True,
|
|
640
644
|
'doc': 'The type of organization.',
|
|
641
645
|
}),
|
|
646
|
+
('motto', ('lang:phrase', {}), {
|
|
647
|
+
'doc': 'The motto used by the organization.'}),
|
|
648
|
+
|
|
642
649
|
('orgtype', ('ou:orgtype', {}), {
|
|
643
650
|
'doc': 'The type of organization.',
|
|
644
651
|
'disp': {'hint': 'taxonomy'},
|
|
@@ -775,6 +782,7 @@ class OuModule(s_module.CoreModule):
|
|
|
775
782
|
'deprecated': True,
|
|
776
783
|
'doc': 'A list of types that apply to the contract.'}),
|
|
777
784
|
)),
|
|
785
|
+
('ou:industry:type:taxonomy', {}, ()),
|
|
778
786
|
('ou:industry', {}, (
|
|
779
787
|
|
|
780
788
|
('name', ('ou:industryname', {}), {
|
synapse/models/risk.py
CHANGED
|
@@ -648,12 +648,21 @@ class RiskModule(s_module.CoreModule):
|
|
|
648
648
|
)),
|
|
649
649
|
|
|
650
650
|
('risk:vulnerable', {}, (
|
|
651
|
+
|
|
651
652
|
('vuln', ('risk:vuln', {}), {
|
|
652
653
|
'doc': 'The vulnerability that the node is susceptible to.'}),
|
|
654
|
+
|
|
653
655
|
('period', ('ival', {}), {
|
|
654
656
|
'doc': 'The time window where the node was vulnerable.'}),
|
|
657
|
+
|
|
655
658
|
('node', ('ndef', {}), {
|
|
656
659
|
'doc': 'The node which is vulnerable.'}),
|
|
660
|
+
|
|
661
|
+
('mitigated', ('bool', {}), {
|
|
662
|
+
'doc': 'Set to true if the vulnerable node has been mitigated.'}),
|
|
663
|
+
|
|
664
|
+
('mitigations', ('array', {'type': 'risk:mitigation', 'sorted': True, 'uniq': True}), {
|
|
665
|
+
'doc': 'The mitigations which were used to address the vulnerable node.'}),
|
|
657
666
|
)),
|
|
658
667
|
|
|
659
668
|
('risk:alert:taxonomy', {}, {}),
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
function foo() {
|
|
2
|
+
if $lib.true {
|
|
3
|
+
stop
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
if $lib.false { $lib.print("no cover") } // pragma: no cover
|
|
7
|
+
|
|
8
|
+
if $lib.false { // pragma: no cover start
|
|
9
|
+
$lib.print("multi-line no cover")
|
|
10
|
+
} // pragma: no cover stop
|
|
11
|
+
|
|
12
|
+
if $lib.false { $lib.print("stop before start") } // pragma: no cover stop
|
|
13
|
+
|
|
14
|
+
if $lib.false { // pragma: no cover start
|
|
15
|
+
$lib.print("start in a block") // pragma: no cover start
|
|
16
|
+
} // pragma: no cover stop
|
|
17
|
+
}
|
|
18
|
+
yield $foo()
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import synapse.assets as s_assets
|
|
3
|
+
|
|
4
|
+
import synapse.tests.utils as s_t_utils
|
|
5
|
+
|
|
6
|
+
class TestAssets(s_t_utils.SynTest):
|
|
7
|
+
|
|
8
|
+
def test_assets_path(self):
|
|
9
|
+
|
|
10
|
+
fp = s_assets.getAssetPath('storm', 'migrations', 'model-0.2.28.storm')
|
|
11
|
+
self.true(os.path.isfile(fp))
|
|
12
|
+
|
|
13
|
+
with self.raises(ValueError) as cm:
|
|
14
|
+
s_assets.getAssetPath('../../../../../../../etc/passwd')
|
|
15
|
+
self.isin('Path escaping', str(cm.exception))
|
|
16
|
+
|
|
17
|
+
with self.raises(ValueError) as cm:
|
|
18
|
+
s_assets.getAssetPath('newp', 'does', 'not', 'exit')
|
|
19
|
+
self.isin('Asset does not exist', str(cm.exception))
|
|
20
|
+
|
|
21
|
+
def test_assets_storm(self):
|
|
22
|
+
|
|
23
|
+
text = s_assets.getStorm('migrations', 'model-0.2.28.storm')
|
|
24
|
+
self.isinstance(text, str)
|
|
25
|
+
self.gt(len(text), 0)
|
synapse/tests/test_cortex.py
CHANGED
|
@@ -4827,6 +4827,45 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
4827
4827
|
q = '$valu={[test:str=foo]} switch $valu { foo: {test:str=foo return($node.value()) } }'
|
|
4828
4828
|
self.eq('foo', await core.callStorm(q))
|
|
4829
4829
|
|
|
4830
|
+
# multi-value switch cases
|
|
4831
|
+
q = '''
|
|
4832
|
+
[test:str=$inval]
|
|
4833
|
+
switch $node.value() {
|
|
4834
|
+
"foo": { return($node.value()) }
|
|
4835
|
+
("boo", "bar"): { return($node.value()) }
|
|
4836
|
+
(coo, car): { return($node.value()) }
|
|
4837
|
+
('doo', 'dar'): { return($node.value()) }
|
|
4838
|
+
("goo", 'gar', gaz): { return($node.value()) }
|
|
4839
|
+
}
|
|
4840
|
+
$lib.raise(BadArg, `Failed match on {$inval}`)
|
|
4841
|
+
'''
|
|
4842
|
+
for inval in ('foo', 'boo', 'bar', 'coo', 'car', 'doo', 'dar', 'goo', 'gar', 'gaz'):
|
|
4843
|
+
valu = await core.callStorm(q, opts={'vars': {'inval': inval}})
|
|
4844
|
+
self.eq(valu, inval)
|
|
4845
|
+
|
|
4846
|
+
# bare asterisk is allowed as a multi-value
|
|
4847
|
+
valu = await core.callStorm('$foo="*" switch $foo { *:{ return(default) } (someval, *): { return(multi) } }')
|
|
4848
|
+
self.eq(valu, 'multi')
|
|
4849
|
+
|
|
4850
|
+
# multiple default cases is invalid
|
|
4851
|
+
msgs = await core.stormlist('$foo=foo switch $foo { *:{} *:{} }')
|
|
4852
|
+
self.stormIsInErr('Switch statements cannot have more than one default case. Found 2.', msgs)
|
|
4853
|
+
|
|
4854
|
+
# multi-value case without a comma
|
|
4855
|
+
msgs = await core.stormlist('$foo=foo switch $foo { (foo bar): { $lib.print(woot) } }')
|
|
4856
|
+
self.stormIsInErr('Unexpected token', msgs)
|
|
4857
|
+
self.stormIsInErr('expecting one of: case multi-value, double-quoted string, single-quoted string', msgs)
|
|
4858
|
+
|
|
4859
|
+
# multi-value case without a second value
|
|
4860
|
+
msgs = await core.stormlist('$foo=foo switch $foo { (foo, ): { $lib.print(woot) } }')
|
|
4861
|
+
self.stormIsInErr('Unexpected token', msgs)
|
|
4862
|
+
self.stormIsInErr('expecting one of: case multi-value, double-quoted string, single-quoted string', msgs)
|
|
4863
|
+
|
|
4864
|
+
# multi-value case without a comma or second value
|
|
4865
|
+
msgs = await core.stormlist('$foo=foo switch $foo { (foo): { $lib.print(woot) } }')
|
|
4866
|
+
self.stormIsInErr('Unexpected token', msgs)
|
|
4867
|
+
self.stormIsInErr('expecting one of: ,', msgs)
|
|
4868
|
+
|
|
4830
4869
|
async def test_storm_tagvar(self):
|
|
4831
4870
|
|
|
4832
4871
|
async with self.getTestCore() as core:
|
|
@@ -7861,17 +7900,23 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
7861
7900
|
'view': view.iden,
|
|
7862
7901
|
})
|
|
7863
7902
|
|
|
7903
|
+
othr = s_common.guid()
|
|
7864
7904
|
info4 = await core.addHttpExtApi({
|
|
7905
|
+
'iden': othr,
|
|
7865
7906
|
'path': 'another/item',
|
|
7866
7907
|
'owner': unfo.get('iden'),
|
|
7867
7908
|
'view': view.iden,
|
|
7868
7909
|
})
|
|
7910
|
+
self.eq(info4.get('iden'), othr)
|
|
7869
7911
|
|
|
7870
7912
|
iden = info.get('iden')
|
|
7871
7913
|
|
|
7872
7914
|
adef = await core.getHttpExtApi(iden)
|
|
7873
7915
|
self.eq(adef, info)
|
|
7874
7916
|
|
|
7917
|
+
adef = await core.getHttpExtApi(othr)
|
|
7918
|
+
self.eq(adef, info4)
|
|
7919
|
+
|
|
7875
7920
|
adef, args = await core.getHttpExtApiByPath('test/path/hehe/wow')
|
|
7876
7921
|
self.eq(adef, info)
|
|
7877
7922
|
self.eq(args, ('hehe', 'wow'))
|
|
@@ -7916,6 +7961,23 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
7916
7961
|
|
|
7917
7962
|
# Sad path
|
|
7918
7963
|
|
|
7964
|
+
with self.raises(s_exc.SchemaViolation):
|
|
7965
|
+
await core.addHttpExtApi({
|
|
7966
|
+
'iden': 'lolnope',
|
|
7967
|
+
'path': 'not/gonna/happen',
|
|
7968
|
+
'owner': unfo.get('iden'),
|
|
7969
|
+
'view': view.iden
|
|
7970
|
+
})
|
|
7971
|
+
|
|
7972
|
+
with self.raises(s_exc.DupIden) as ectx:
|
|
7973
|
+
await core.addHttpExtApi({
|
|
7974
|
+
'iden': othr,
|
|
7975
|
+
'path': 'bad/dup',
|
|
7976
|
+
'owner': unfo.get('iden'),
|
|
7977
|
+
'view': view.iden
|
|
7978
|
+
})
|
|
7979
|
+
self.eq(ectx.exception.get('iden'), othr)
|
|
7980
|
+
|
|
7919
7981
|
with self.raises(s_exc.SynErr):
|
|
7920
7982
|
await core.setHttpApiIndx(newp, 0)
|
|
7921
7983
|
|
|
@@ -7953,6 +8015,10 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
7953
8015
|
|
|
7954
8016
|
async def test_cortex_query_offload(self):
|
|
7955
8017
|
|
|
8018
|
+
async def _hang(*args, **kwargs):
|
|
8019
|
+
await asyncio.sleep(6)
|
|
8020
|
+
return
|
|
8021
|
+
|
|
7956
8022
|
async with self.getTestAha() as aha:
|
|
7957
8023
|
|
|
7958
8024
|
async with await s_base.Base.anit() as base:
|
|
@@ -8028,8 +8094,61 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
8028
8094
|
self.isin('Offloading Storm query', data)
|
|
8029
8095
|
self.notin('Timeout', data)
|
|
8030
8096
|
|
|
8097
|
+
with patch('synapse.cortex.CoreApi.getNexsIndx', _hang):
|
|
8098
|
+
|
|
8099
|
+
with self.getLoggerStream('synapse') as stream:
|
|
8100
|
+
msgs = await alist(core00.storm('inet:asn=0'))
|
|
8101
|
+
self.len(1, [m for m in msgs if m[0] == 'node'])
|
|
8102
|
+
|
|
8103
|
+
stream.seek(0)
|
|
8104
|
+
data = stream.read()
|
|
8105
|
+
self.notin('Offloading Storm query', data)
|
|
8106
|
+
self.isin('Timeout waiting for pool mirror [01.core.synapse] Nexus offset', data)
|
|
8107
|
+
self.notin('Timeout waiting for query mirror', data)
|
|
8108
|
+
|
|
8109
|
+
await core00.stormpool.waitready(timeout=12)
|
|
8110
|
+
|
|
8111
|
+
with patch('synapse.telepath.Proxy.getPoolLink', _hang):
|
|
8112
|
+
|
|
8113
|
+
with self.getLoggerStream('synapse') as stream:
|
|
8114
|
+
msgs = await alist(core00.storm('inet:asn=0'))
|
|
8115
|
+
self.len(1, [m for m in msgs if m[0] == 'node'])
|
|
8116
|
+
|
|
8117
|
+
stream.seek(0)
|
|
8118
|
+
data = stream.read()
|
|
8119
|
+
self.notin('Offloading Storm query', data)
|
|
8120
|
+
self.isin('Timeout waiting for pool mirror [01.core.synapse] Nexus offset', data)
|
|
8121
|
+
self.notin('Timeout waiting for query mirror', data)
|
|
8122
|
+
|
|
8123
|
+
await core00.stormpool.waitready(timeout=12)
|
|
8124
|
+
|
|
8125
|
+
with self.getLoggerStream('synapse') as stream:
|
|
8126
|
+
msgs = await alist(core00.storm('inet:asn=0'))
|
|
8127
|
+
self.len(1, [m for m in msgs if m[0] == 'node'])
|
|
8128
|
+
|
|
8129
|
+
stream.seek(0)
|
|
8130
|
+
data = stream.read()
|
|
8131
|
+
self.isin('Offloading Storm query', data)
|
|
8132
|
+
self.notin('Timeout waiting for pool mirror', data)
|
|
8133
|
+
self.notin('Timeout waiting for query mirror', data)
|
|
8134
|
+
|
|
8031
8135
|
core01.nexsroot.nexslog.indx = 0
|
|
8032
8136
|
|
|
8137
|
+
with patch('synapse.cortex.MAX_NEXUS_DELTA', 1):
|
|
8138
|
+
|
|
8139
|
+
nexsoffs = await core00.getNexsIndx()
|
|
8140
|
+
|
|
8141
|
+
with self.getLoggerStream('synapse') as stream:
|
|
8142
|
+
msgs = await alist(core00.storm('inet:asn=0'))
|
|
8143
|
+
self.len(1, [m for m in msgs if m[0] == 'node'])
|
|
8144
|
+
|
|
8145
|
+
stream.seek(0)
|
|
8146
|
+
data = stream.read()
|
|
8147
|
+
explog = (f'Pool mirror [01.core.synapse] Nexus offset delta too large '
|
|
8148
|
+
f'({nexsoffs} > 1), running query locally')
|
|
8149
|
+
self.isin(explog, data)
|
|
8150
|
+
self.notin('Offloading Storm query', data)
|
|
8151
|
+
|
|
8033
8152
|
with self.getLoggerStream('synapse') as stream:
|
|
8034
8153
|
msgs = await alist(core00.storm('inet:asn=0'))
|
|
8035
8154
|
self.len(1, [m for m in msgs if m[0] == 'node'])
|
|
@@ -8076,6 +8195,16 @@ class CortexBasicTest(s_t_utils.SynTest):
|
|
|
8076
8195
|
with self.raises(s_exc.TimeOut):
|
|
8077
8196
|
await core00.count('inet:asn=0', opts=opts)
|
|
8078
8197
|
|
|
8198
|
+
core00.stormpool.ready.clear()
|
|
8199
|
+
|
|
8200
|
+
with self.getLoggerStream('synapse') as stream:
|
|
8201
|
+
msgs = await alist(core00.storm('inet:asn=0'))
|
|
8202
|
+
self.len(1, [m for m in msgs if m[0] == 'node'])
|
|
8203
|
+
|
|
8204
|
+
stream.seek(0)
|
|
8205
|
+
data = stream.read()
|
|
8206
|
+
self.isin('Timeout waiting for pool mirror, running query locally', data)
|
|
8207
|
+
|
|
8079
8208
|
await core01.fini()
|
|
8080
8209
|
|
|
8081
8210
|
with self.getLoggerStream('synapse') as stream:
|
synapse/tests/test_datamodel.py
CHANGED
|
@@ -63,6 +63,12 @@ class DataModelTest(s_t_utils.SynTest):
|
|
|
63
63
|
with self.raises(s_exc.BadFormDef):
|
|
64
64
|
core.model.addForm('woot:two', {}, ())
|
|
65
65
|
|
|
66
|
+
with self.raises(s_exc.NoSuchForm):
|
|
67
|
+
core.model.reqForm('newp:newp')
|
|
68
|
+
|
|
69
|
+
with self.raises(s_exc.NoSuchProp):
|
|
70
|
+
core.model.reqForm('inet:asn').reqProp('newp')
|
|
71
|
+
|
|
66
72
|
async def test_datamodel_formname(self):
|
|
67
73
|
modl = s_datamodel.Model()
|
|
68
74
|
mods = (
|
|
@@ -619,6 +619,10 @@ Queries = [
|
|
|
619
619
|
switch $foo {
|
|
620
620
|
bar: { [ +#ohai ] break }
|
|
621
621
|
baz: { [ +#visi ] continue }
|
|
622
|
+
(far, faz): { [ +#multi.far ] continue }
|
|
623
|
+
("gar", "gaz"): { [ +#multi.gar ] continue }
|
|
624
|
+
('har', 'haz'): { [ +#multi.har ] continue }
|
|
625
|
+
("kar", 'kaz', koo): { [ +#multi.kar ] continue }
|
|
622
626
|
}
|
|
623
627
|
|
|
624
628
|
[ inet:ipv4=5.6.7.8 ]
|
|
@@ -1251,7 +1255,9 @@ _ParseResults = [
|
|
|
1251
1255
|
'Query: [EditNodeAdd: [FormName: [Const: test:str], Const: =, Const: c], SwitchCase: [VarValue: [Const: woot], CaseEntry: [Const: hehe, SubQuery: [Query: [EditTagAdd: [TagName: [Const: baz]]]]], CaseEntry: [SubQuery: [Query: [EditTagAdd: [TagName: [Const: jaz]]]]]]]',
|
|
1252
1256
|
'Query: [EditNodeAdd: [FormName: [Const: test:str], Const: =, Const: c], SwitchCase: [VarValue: [Const: woot], CaseEntry: [Const: hehe, SubQuery: [Query: [EditTagAdd: [TagName: [Const: baz]]]]], CaseEntry: [Const: haha hoho, SubQuery: [Query: [EditTagAdd: [TagName: [Const: faz]]]]], CaseEntry: [Const: lolz:lulz, SubQuery: [Query: [EditTagAdd: [TagName: [Const: jaz]]]]]]]',
|
|
1253
1257
|
'Query: [EditNodeAdd: [FormName: [Const: inet:ipv4], Const: =, Const: 1.2.3.4], SwitchCase: [VarValue: [Const: foo], CaseEntry: [Const: bar, SubQuery: [Query: [EditTagAdd: [TagName: [Const: hehe, Const: haha]]]]], CaseEntry: [Const: baz faz, SubQuery: [Query: []]]]]',
|
|
1254
|
-
|
|
1258
|
+
|
|
1259
|
+
'Query: [ForLoop: [Const: foo, VarValue: [Const: foos], SubQuery: [Query: [EditNodeAdd: [FormName: [Const: inet:ipv4], Const: =, Const: 1.2.3.4], SwitchCase: [VarValue: [Const: foo], CaseEntry: [Const: bar, SubQuery: [Query: [EditTagAdd: [TagName: [Const: ohai]], BreakOper: []]]], CaseEntry: [Const: baz, SubQuery: [Query: [EditTagAdd: [TagName: [Const: visi]], ContinueOper: []]]], CaseEntry: [Const: far, Const: faz, SubQuery: [Query: [EditTagAdd: [TagName: [Const: multi, Const: far]], ContinueOper: []]]], CaseEntry: [Const: gar, Const: gaz, SubQuery: [Query: [EditTagAdd: [TagName: [Const: multi, Const: gar]], ContinueOper: []]]], CaseEntry: [Const: har, Const: haz, SubQuery: [Query: [EditTagAdd: [TagName: [Const: multi, Const: har]], ContinueOper: []]]], CaseEntry: [Const: kar, Const: kaz, Const: koo, SubQuery: [Query: [EditTagAdd: [TagName: [Const: multi, Const: kar]], ContinueOper: []]]]], EditNodeAdd: [FormName: [Const: inet:ipv4], Const: =, Const: 5.6.7.8], EditTagAdd: [TagName: [Const: hehe]]]]]]',
|
|
1260
|
+
|
|
1255
1261
|
'Query: [SwitchCase: [VarValue: [Const: a], CaseEntry: [Const: a, SubQuery: [Query: []]]]]',
|
|
1256
1262
|
'Query: [SwitchCase: [VarValue: [Const: a], CaseEntry: [Const: test:str, SubQuery: [Query: []]], CaseEntry: [SubQuery: [Query: []]]]]',
|
|
1257
1263
|
'Query: [SwitchCase: [VarValue: [Const: a], CaseEntry: [Const: test:this:works:, SubQuery: [Query: []]], CaseEntry: [SubQuery: [Query: []]]]]',
|
synapse/tests/test_lib_layer.py
CHANGED
|
@@ -2238,3 +2238,38 @@ class LayerTest(s_t_utils.SynTest):
|
|
|
2238
2238
|
self.false(layr.nodeeditslab.lenv.flags()['readahead'])
|
|
2239
2239
|
self.false(layr.dataslab.readahead)
|
|
2240
2240
|
self.false(layr.dataslab.lenv.flags()['readahead'])
|
|
2241
|
+
|
|
2242
|
+
async def test_layer_delete_with_nodedata(self):
|
|
2243
|
+
|
|
2244
|
+
async with self.getTestCore() as core:
|
|
2245
|
+
|
|
2246
|
+
fork00 = await core.view.fork()
|
|
2247
|
+
infork00 = {'view': fork00['iden']}
|
|
2248
|
+
layr00 = core.getLayer(fork00['layers'][0]['iden'])
|
|
2249
|
+
|
|
2250
|
+
iden = await core.callStorm('[ inet:ipv4=1.2.3.4 ] return($node.iden())')
|
|
2251
|
+
|
|
2252
|
+
sodes = await s_t_utils.alist(layr00.getStorNodesByForm('inet:ipv4'))
|
|
2253
|
+
self.len(0, sodes)
|
|
2254
|
+
|
|
2255
|
+
q = '''
|
|
2256
|
+
inet:ipv4=1.2.3.4
|
|
2257
|
+
$node.data.set("key", "valu")
|
|
2258
|
+
'''
|
|
2259
|
+
await core.callStorm(q, opts=infork00)
|
|
2260
|
+
|
|
2261
|
+
sodes = await s_t_utils.alist(layr00.getStorNodesByForm('inet:ipv4'))
|
|
2262
|
+
self.len(1, sodes)
|
|
2263
|
+
|
|
2264
|
+
q = '''
|
|
2265
|
+
view.exec $fork00 {
|
|
2266
|
+
yield $iden
|
|
2267
|
+
$lib.print($node)
|
|
2268
|
+
delnode --deledges --force
|
|
2269
|
+
}
|
|
2270
|
+
'''
|
|
2271
|
+
opts = {'vars': {'iden': iden, 'fork00': fork00['iden']}}
|
|
2272
|
+
await core.callStorm(q, opts=opts)
|
|
2273
|
+
|
|
2274
|
+
sodes = await s_t_utils.alist(layr00.getStorNodesByForm('inet:ipv4'))
|
|
2275
|
+
self.len(0, sodes)
|
|
@@ -295,8 +295,9 @@ class LmdbSlabTest(s_t_utils.SynTest):
|
|
|
295
295
|
self.eq(items, ((b'\x00\x02', b'haha'), (b'\x00\x01', b'hehe')))
|
|
296
296
|
|
|
297
297
|
# Copy a database inside the same slab
|
|
298
|
-
self.raises(s_exc.DataAlreadyExists
|
|
299
|
-
|
|
298
|
+
with self.raises(s_exc.DataAlreadyExists):
|
|
299
|
+
await slab.copydb(foo, slab, 'bar')
|
|
300
|
+
self.eq(3, await slab.copydb(foo, slab, 'foo2'))
|
|
300
301
|
|
|
301
302
|
# Increase the size of the new source DB to trigger a resize on the next copydb
|
|
302
303
|
foo2 = slab.initdb('foo2')
|
|
@@ -312,7 +313,7 @@ class LmdbSlabTest(s_t_utils.SynTest):
|
|
|
312
313
|
async with await s_lmdbslab.Slab.anit(path2, map_size=512 * 1024) as slab2:
|
|
313
314
|
with patch('synapse.lib.lmdbslab.PROGRESS_PERIOD', 2):
|
|
314
315
|
|
|
315
|
-
self.eq(4, slab.copydb(foo2, slab2, destdbname='foo2', progresscb=progfunc))
|
|
316
|
+
self.eq(4, await slab.copydb(foo2, slab2, destdbname='foo2', progresscb=progfunc))
|
|
316
317
|
self.gt(vardict.get('prog', 0), 0)
|
|
317
318
|
|
|
318
319
|
# Test slab.drop and slab.dbexists
|
|
@@ -808,7 +809,8 @@ class LmdbSlabTest(s_t_utils.SynTest):
|
|
|
808
809
|
self.raises(s_exc.IsReadOnly, newdb.replace, b'1234', b'3456')
|
|
809
810
|
self.raises(s_exc.IsReadOnly, newdb.pop, b'1234')
|
|
810
811
|
self.raises(s_exc.IsReadOnly, newdb.delete, b'1234')
|
|
811
|
-
self.raises(s_exc.IsReadOnly
|
|
812
|
+
with self.raises(s_exc.IsReadOnly):
|
|
813
|
+
await newdb.putmulti((b'1234', b'3456'))
|
|
812
814
|
|
|
813
815
|
# While we have the DB open in readonly, have another process write a bunch of data to cause the
|
|
814
816
|
# map size to be increased
|
|
@@ -836,7 +838,7 @@ class LmdbSlabTest(s_t_utils.SynTest):
|
|
|
836
838
|
# A putmulti across a grow
|
|
837
839
|
before_mapsize = slab.mapsize
|
|
838
840
|
kvpairs = [(x, x) for x in data]
|
|
839
|
-
retn = slab.putmulti(kvpairs)
|
|
841
|
+
retn = await slab.putmulti(kvpairs)
|
|
840
842
|
self.eq(retn, (1000, 1000))
|
|
841
843
|
|
|
842
844
|
after_mapsize1 = slab.mapsize
|
|
@@ -844,7 +846,7 @@ class LmdbSlabTest(s_t_utils.SynTest):
|
|
|
844
846
|
|
|
845
847
|
# A putmulti across a grow with a generator passed in
|
|
846
848
|
kvpairs = ((b' ' + x, x) for x in data)
|
|
847
|
-
retn = slab.putmulti(kvpairs)
|
|
849
|
+
retn = await slab.putmulti(kvpairs)
|
|
848
850
|
self.eq(retn, (1000, 1000))
|
|
849
851
|
after_mapsize2 = slab.mapsize
|
|
850
852
|
self.gt(after_mapsize2, after_mapsize1)
|
|
@@ -1011,7 +1013,7 @@ class LmdbSlabTest(s_t_utils.SynTest):
|
|
|
1011
1013
|
async with await s_lmdbslab.Slab.anit(path, map_size=32000, growsize=5000) as slab:
|
|
1012
1014
|
slab.initdb('foo')
|
|
1013
1015
|
kvpairs = [(x, x) for x in data]
|
|
1014
|
-
slab.putmulti(kvpairs)
|
|
1016
|
+
await slab.putmulti(kvpairs)
|
|
1015
1017
|
slab.forcecommit()
|
|
1016
1018
|
before_mapsize = slab.mapsize
|
|
1017
1019
|
slab.dropdb('foo')
|
|
@@ -1029,7 +1031,7 @@ class LmdbSlabTest(s_t_utils.SynTest):
|
|
|
1029
1031
|
async with await s_lmdbslab.Slab.anit(path, map_size=32000, growsize=5000) as slab:
|
|
1030
1032
|
slab.initdb('foo')
|
|
1031
1033
|
kvpairs = [(x, x) for x in data]
|
|
1032
|
-
slab.putmulti(kvpairs)
|
|
1034
|
+
await slab.putmulti(kvpairs)
|
|
1033
1035
|
slab.forcecommit()
|
|
1034
1036
|
|
|
1035
1037
|
asyncio.run(workloop())
|
|
@@ -1047,7 +1049,7 @@ class LmdbSlabTest(s_t_utils.SynTest):
|
|
|
1047
1049
|
|
|
1048
1050
|
proc = mpctx.Process(target=self.make_slab, args=(path,))
|
|
1049
1051
|
proc.start()
|
|
1050
|
-
proc.join(
|
|
1052
|
+
proc.join(20)
|
|
1051
1053
|
self.nn(proc.exitcode)
|
|
1052
1054
|
slab.initdb('foo')
|
|
1053
1055
|
self.true(True)
|