synapse 2.154.1__py311-none-any.whl → 2.156.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/cmds/cortex.py +2 -14
- synapse/common.py +13 -36
- synapse/cortex.py +15 -508
- synapse/lib/ast.py +215 -22
- synapse/lib/cell.py +35 -8
- synapse/lib/certdir.py +11 -0
- synapse/lib/cmdr.py +0 -5
- synapse/lib/gis.py +2 -2
- synapse/lib/httpapi.py +14 -43
- synapse/lib/layer.py +64 -201
- synapse/lib/lmdbslab.py +11 -0
- synapse/lib/node.py +1 -3
- synapse/lib/parser.py +10 -0
- synapse/lib/slabseqn.py +2 -1
- synapse/lib/snap.py +121 -21
- synapse/lib/spooled.py +9 -0
- synapse/lib/storm.lark +23 -6
- synapse/lib/storm.py +16 -339
- synapse/lib/storm_format.py +5 -0
- synapse/lib/stormhttp.py +10 -1
- synapse/lib/stormlib/gen.py +1 -2
- synapse/lib/stormlib/gis.py +41 -0
- synapse/lib/stormlib/graph.py +2 -1
- synapse/lib/stormlib/stats.py +21 -2
- synapse/lib/stormlib/storm.py +16 -1
- synapse/lib/stormtypes.py +244 -16
- synapse/lib/types.py +16 -2
- synapse/lib/version.py +2 -2
- synapse/lib/view.py +118 -25
- synapse/models/base.py +2 -2
- synapse/models/inet.py +60 -30
- synapse/models/infotech.py +130 -8
- synapse/models/orgs.py +3 -0
- synapse/models/proj.py +3 -0
- synapse/models/risk.py +24 -6
- synapse/models/syn.py +0 -38
- synapse/tests/test_cmds_cortex.py +1 -1
- synapse/tests/test_cortex.py +70 -338
- synapse/tests/test_lib_agenda.py +19 -54
- synapse/tests/test_lib_aha.py +97 -0
- synapse/tests/test_lib_ast.py +596 -0
- synapse/tests/test_lib_grammar.py +30 -10
- synapse/tests/test_lib_httpapi.py +33 -49
- synapse/tests/test_lib_layer.py +19 -234
- synapse/tests/test_lib_lmdbslab.py +22 -0
- synapse/tests/test_lib_snap.py +9 -0
- synapse/tests/test_lib_spooled.py +4 -0
- synapse/tests/test_lib_storm.py +16 -309
- synapse/tests/test_lib_stormlib_gis.py +21 -0
- synapse/tests/test_lib_stormlib_stats.py +107 -20
- synapse/tests/test_lib_stormlib_storm.py +25 -0
- synapse/tests/test_lib_stormtypes.py +253 -8
- synapse/tests/test_lib_types.py +40 -0
- synapse/tests/test_lib_view.py +6 -13
- synapse/tests/test_model_base.py +1 -1
- synapse/tests/test_model_inet.py +15 -0
- synapse/tests/test_model_infotech.py +110 -0
- synapse/tests/test_model_orgs.py +10 -0
- synapse/tests/test_model_person.py +0 -3
- synapse/tests/test_model_proj.py +2 -1
- synapse/tests/test_model_risk.py +24 -0
- synapse/tests/test_model_syn.py +20 -34
- synapse/tests/test_tools_csvtool.py +2 -1
- synapse/tests/test_tools_feed.py +4 -30
- synapse/tools/csvtool.py +2 -1
- {synapse-2.154.1.dist-info → synapse-2.156.0.dist-info}/METADATA +9 -9
- {synapse-2.154.1.dist-info → synapse-2.156.0.dist-info}/RECORD +70 -72
- {synapse-2.154.1.dist-info → synapse-2.156.0.dist-info}/WHEEL +1 -1
- synapse/cmds/cron.py +0 -726
- synapse/cmds/trigger.py +0 -319
- synapse/tests/test_cmds_cron.py +0 -453
- synapse/tests/test_cmds_trigger.py +0 -176
- {synapse-2.154.1.dist-info → synapse-2.156.0.dist-info}/LICENSE +0 -0
- {synapse-2.154.1.dist-info → synapse-2.156.0.dist-info}/top_level.txt +0 -0
synapse/tests/test_lib_ast.py
CHANGED
|
@@ -656,6 +656,109 @@ class AstTest(s_test.SynTest):
|
|
|
656
656
|
self.len(0, await core.nodes('[ inet:ipv4=1.2.3.4 ] :foo -> *'))
|
|
657
657
|
self.len(0, await core.nodes('[ inet:ipv4=1.2.3.4 ] :asn -> inet:asn'))
|
|
658
658
|
|
|
659
|
+
async def test_ast_edge_walknjoin(self):
|
|
660
|
+
|
|
661
|
+
async with self.getTestCore() as core:
|
|
662
|
+
|
|
663
|
+
await core.nodes('[test:str=foo :hehe=bar +(foobar)> { [ test:str=baz ] }]')
|
|
664
|
+
|
|
665
|
+
nodes = await core.nodes('test:str=foo --+> *')
|
|
666
|
+
self.len(2, nodes)
|
|
667
|
+
self.eq(('test:str', 'foo'), nodes[0].ndef)
|
|
668
|
+
self.eq(('test:str', 'baz'), nodes[1].ndef)
|
|
669
|
+
|
|
670
|
+
nodes = await core.nodes('test:str=baz <+-- *')
|
|
671
|
+
self.len(2, nodes)
|
|
672
|
+
self.eq(('test:str', 'baz'), nodes[0].ndef)
|
|
673
|
+
self.eq(('test:str', 'foo'), nodes[1].ndef)
|
|
674
|
+
|
|
675
|
+
nodes = await core.nodes('test:str=foo -(foobar)+> *')
|
|
676
|
+
self.len(2, nodes)
|
|
677
|
+
self.eq(('test:str', 'foo'), nodes[0].ndef)
|
|
678
|
+
self.eq(('test:str', 'baz'), nodes[1].ndef)
|
|
679
|
+
|
|
680
|
+
nodes = await core.nodes('test:str=baz <+(foobar)- *')
|
|
681
|
+
self.len(2, nodes)
|
|
682
|
+
self.eq(('test:str', 'baz'), nodes[0].ndef)
|
|
683
|
+
self.eq(('test:str', 'foo'), nodes[1].ndef)
|
|
684
|
+
|
|
685
|
+
await core.nodes('test:str=foo [ +(coffeeone)> { [ test:str=arabica ] } ]')
|
|
686
|
+
await core.nodes('test:str=foo [ +(coffeetwo)> { [ test:str=robusta ] } ]')
|
|
687
|
+
await core.nodes('[ test:int=28 +(coffeethree)> { test:str=arabica } ]')
|
|
688
|
+
|
|
689
|
+
nodes = await core.nodes('test:str=foo -((coffeeone, coffeetwo))+> *')
|
|
690
|
+
self.len(3, nodes)
|
|
691
|
+
self.eq(('test:str', 'foo'), nodes[0].ndef)
|
|
692
|
+
self.eq(('test:str', 'arabica'), nodes[1].ndef)
|
|
693
|
+
self.eq(('test:str', 'robusta'), nodes[2].ndef)
|
|
694
|
+
|
|
695
|
+
await core.nodes('[test:str=neato :hehe=haha +(stuff)> { [inet:ipv4=1.2.3.0/24] }]')
|
|
696
|
+
await core.nodes('[test:str=burrito :hehe=stuff <(stuff)+ { test:str=baz }]')
|
|
697
|
+
await core.nodes('test:str=neato [ <(other)+ { test:str=foo } ]')
|
|
698
|
+
|
|
699
|
+
nodes = await core.nodes('$edge=stuff test:str=neato -($edge)+> *')
|
|
700
|
+
self.len(257, nodes)
|
|
701
|
+
self.eq(('test:str', 'neato'), nodes[0].ndef)
|
|
702
|
+
for n in nodes[1:]:
|
|
703
|
+
self.eq('inet:ipv4', n.ndef[0])
|
|
704
|
+
|
|
705
|
+
nodes = await core.nodes('test:str=neato | tee { --+> * } { <+(other)- * }')
|
|
706
|
+
self.len(259, nodes)
|
|
707
|
+
self.eq(('test:str', 'neato'), nodes[0].ndef)
|
|
708
|
+
self.eq(('test:str', 'foo'), nodes[-1].ndef)
|
|
709
|
+
self.eq(('test:str', 'neato'), nodes[-2].ndef)
|
|
710
|
+
|
|
711
|
+
for n in nodes[1:257]:
|
|
712
|
+
self.eq('inet:ipv4', n.ndef[0])
|
|
713
|
+
|
|
714
|
+
await core.nodes('test:str=foo [ +(wat)> {[test:int=12]}]')
|
|
715
|
+
|
|
716
|
+
nodes = await core.nodes('test:str=foo -(other)+> test:str')
|
|
717
|
+
self.len(2, nodes)
|
|
718
|
+
self.eq(('test:str', 'foo'), nodes[0].ndef)
|
|
719
|
+
self.eq(('test:str', 'neato'), nodes[1].ndef)
|
|
720
|
+
|
|
721
|
+
with self.raises(s_exc.BadSyntax):
|
|
722
|
+
await core.nodes('test:str=neato --+> test:str')
|
|
723
|
+
|
|
724
|
+
with self.raises(s_exc.BadSyntax):
|
|
725
|
+
await core.nodes('test:str <+-- test:str')
|
|
726
|
+
|
|
727
|
+
nodes = await core.nodes('test:str=foo -(*)+> test:str')
|
|
728
|
+
self.len(5, nodes)
|
|
729
|
+
self.eq(('test:str', 'foo'), nodes[0].ndef)
|
|
730
|
+
ndefs = [n.ndef for n in nodes[1:]]
|
|
731
|
+
self.isin(('test:str', 'arabica'), ndefs)
|
|
732
|
+
self.isin(('test:str', 'robusta'), ndefs)
|
|
733
|
+
self.isin(('test:str', 'baz'), ndefs)
|
|
734
|
+
self.isin(('test:str', 'neato'), ndefs)
|
|
735
|
+
self.notin(('test:int', 12), ndefs)
|
|
736
|
+
|
|
737
|
+
nodes = await core.nodes('test:str=foo -(*)+> *')
|
|
738
|
+
self.len(6, nodes)
|
|
739
|
+
self.eq(('test:str', 'foo'), nodes[0].ndef)
|
|
740
|
+
ndefs = [n.ndef for n in nodes[1:]]
|
|
741
|
+
self.isin(('test:int', 12), ndefs)
|
|
742
|
+
|
|
743
|
+
nodes = await core.nodes('test:str=arabica <+(*)- test:str')
|
|
744
|
+
self.len(2, nodes)
|
|
745
|
+
self.eq(('test:str', 'arabica'), nodes[0].ndef)
|
|
746
|
+
self.eq(('test:str', 'foo'), nodes[1].ndef)
|
|
747
|
+
|
|
748
|
+
nodes = await core.nodes('test:str=arabica <+(*)- *')
|
|
749
|
+
self.len(3, nodes)
|
|
750
|
+
self.eq(('test:str', 'arabica'), nodes[0].ndef)
|
|
751
|
+
ndefs = [n.ndef for n in nodes[1:]]
|
|
752
|
+
self.isin(('test:str', 'foo'), ndefs)
|
|
753
|
+
self.isin(('test:int', 28), ndefs)
|
|
754
|
+
|
|
755
|
+
await core.nodes('test:str=arabica [ <(place)+ { [ test:str=coffeebar] } ]')
|
|
756
|
+
nodes = await core.nodes('test:str=arabica <+((place, coffeeone))- *')
|
|
757
|
+
self.len(3, nodes)
|
|
758
|
+
self.eq(('test:str', 'arabica'), nodes[0].ndef)
|
|
759
|
+
self.eq(('test:str', 'coffeebar'), nodes[1].ndef)
|
|
760
|
+
self.eq(('test:str', 'foo'), nodes[2].ndef)
|
|
761
|
+
|
|
659
762
|
async def test_ast_lift_filt_array(self):
|
|
660
763
|
|
|
661
764
|
async with self.getTestCore() as core:
|
|
@@ -1738,6 +1841,243 @@ class AstTest(s_test.SynTest):
|
|
|
1738
1841
|
evnt = firs[0]
|
|
1739
1842
|
self.eq(evnt[1].get('data'), {'total': 3})
|
|
1740
1843
|
|
|
1844
|
+
async def test_ast_emptyblock(self):
|
|
1845
|
+
|
|
1846
|
+
async with self.getTestCore() as core:
|
|
1847
|
+
q = '''
|
|
1848
|
+
empty {
|
|
1849
|
+
$lib.print("a fancy but empty block")
|
|
1850
|
+
}
|
|
1851
|
+
'''
|
|
1852
|
+
msgs = await core.stormlist(q)
|
|
1853
|
+
self.stormIsInPrint('a fancy but empty block', msgs)
|
|
1854
|
+
|
|
1855
|
+
q = '''
|
|
1856
|
+
empty {
|
|
1857
|
+
[test:str=neato]
|
|
1858
|
+
}
|
|
1859
|
+
[ :hehe=stuff ]
|
|
1860
|
+
'''
|
|
1861
|
+
msgs = await core.stormlist(q)
|
|
1862
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
1863
|
+
self.len(1, nodes)
|
|
1864
|
+
props = nodes[0][1]['props']
|
|
1865
|
+
self.eq('stuff', props.get('hehe'))
|
|
1866
|
+
|
|
1867
|
+
q = '''
|
|
1868
|
+
empty {
|
|
1869
|
+
$lib.print("some empty block")
|
|
1870
|
+
}
|
|
1871
|
+
[test:str=synapse]
|
|
1872
|
+
'''
|
|
1873
|
+
msgs = await core.stormlist(q)
|
|
1874
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
1875
|
+
self.len(1, nodes)
|
|
1876
|
+
self.stormIsInPrint('some empty block', msgs)
|
|
1877
|
+
|
|
1878
|
+
q = '''
|
|
1879
|
+
for $i in $lib.range(10) {
|
|
1880
|
+
if ($i > 5) {
|
|
1881
|
+
[test:int=$i]
|
|
1882
|
+
}
|
|
1883
|
+
} | empty { $lib.print(`count is {$i}`) }
|
|
1884
|
+
'''
|
|
1885
|
+
msgs = await core.stormlist(q)
|
|
1886
|
+
self.stormNotInPrint('count is', msgs)
|
|
1887
|
+
|
|
1888
|
+
q = '''
|
|
1889
|
+
for $i in $lib.range(10) {
|
|
1890
|
+
$lib.print(`count is {$i}`)
|
|
1891
|
+
} | empty { $lib.print(`pipeline is empty`) }
|
|
1892
|
+
'''
|
|
1893
|
+
msgs = await core.stormlist(q)
|
|
1894
|
+
self.stormIsInPrint('count is', msgs)
|
|
1895
|
+
self.stormIsInPrint('pipeline is empty', msgs)
|
|
1896
|
+
|
|
1897
|
+
q = '''
|
|
1898
|
+
[test:str=burrito]
|
|
1899
|
+
empty {
|
|
1900
|
+
[test:str=awesome]
|
|
1901
|
+
}
|
|
1902
|
+
'''
|
|
1903
|
+
msgs = await core.stormlist(q)
|
|
1904
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
1905
|
+
self.len(1, nodes)
|
|
1906
|
+
self.eq(('test:str', 'burrito'), nodes[0][0])
|
|
1907
|
+
|
|
1908
|
+
q = '''
|
|
1909
|
+
$lib.print("OH YEA")
|
|
1910
|
+
empty {
|
|
1911
|
+
[test:str=possum]
|
|
1912
|
+
}
|
|
1913
|
+
'''
|
|
1914
|
+
msgs = await core.stormlist(q)
|
|
1915
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
1916
|
+
self.len(1, nodes)
|
|
1917
|
+
self.eq(('test:str', 'possum'), nodes[0][0])
|
|
1918
|
+
self.stormIsInPrint('OH YEA', msgs)
|
|
1919
|
+
|
|
1920
|
+
q = '''
|
|
1921
|
+
empty {
|
|
1922
|
+
[test:str=foo]
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1925
|
+
empty {
|
|
1926
|
+
[test:bstr=bar]
|
|
1927
|
+
}
|
|
1928
|
+
'''
|
|
1929
|
+
msgs = await core.stormlist(q)
|
|
1930
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
1931
|
+
self.len(1, nodes)
|
|
1932
|
+
self.eq(('test:str', 'foo'), nodes[0][0])
|
|
1933
|
+
|
|
1934
|
+
q = '''
|
|
1935
|
+
empty {
|
|
1936
|
+
$lib.print('call me')
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
$lib.print('ishmael')
|
|
1940
|
+
|
|
1941
|
+
empty {
|
|
1942
|
+
$lib.print('some years ago')
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
[test:str="moby dick"]
|
|
1946
|
+
|
|
1947
|
+
empty {
|
|
1948
|
+
$lib.print('never mind')
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
empty {
|
|
1952
|
+
$lib.print('how long')
|
|
1953
|
+
}
|
|
1954
|
+
|
|
1955
|
+
[ :hehe=haha ]
|
|
1956
|
+
'''
|
|
1957
|
+
msgs = await core.stormlist(q)
|
|
1958
|
+
self.stormIsInPrint('call me', msgs)
|
|
1959
|
+
self.stormIsInPrint('ishmael', msgs)
|
|
1960
|
+
self.stormIsInPrint('some years ago', msgs)
|
|
1961
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
1962
|
+
self.len(1, nodes)
|
|
1963
|
+
self.eq(('test:str', 'moby dick'), nodes[0][0])
|
|
1964
|
+
self.eq('haha', nodes[0][1]['props']['hehe'])
|
|
1965
|
+
self.stormNotInPrint('never mind', msgs)
|
|
1966
|
+
self.stormNotInPrint('how long', msgs)
|
|
1967
|
+
|
|
1968
|
+
q = '''
|
|
1969
|
+
function foo(x) {
|
|
1970
|
+
empty {
|
|
1971
|
+
$lib.print($x)
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
return()
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
[test:str=biz :hehe=baz]
|
|
1978
|
+
$foo(:hehe)
|
|
1979
|
+
'''
|
|
1980
|
+
msgs = await core.stormlist(q)
|
|
1981
|
+
self.stormIsInPrint("baz", msgs)
|
|
1982
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
1983
|
+
self.len(1, nodes)
|
|
1984
|
+
self.eq(('test:str', 'biz'), nodes[0][0])
|
|
1985
|
+
|
|
1986
|
+
q = '''
|
|
1987
|
+
[test:str=coffee :hehe=pourover] $beep=:hehe | spin | empty { $lib.print("blorp") }
|
|
1988
|
+
'''
|
|
1989
|
+
msgs = await core.stormlist(q)
|
|
1990
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
1991
|
+
self.len(0, nodes)
|
|
1992
|
+
self.stormIsInPrint('blorp', msgs)
|
|
1993
|
+
|
|
1994
|
+
q = '''
|
|
1995
|
+
[test:str=latte :hehe=milk] $beep=:hehe | spin | empty { $lib.print($beep) }
|
|
1996
|
+
'''
|
|
1997
|
+
msgs = await core.stormlist(q)
|
|
1998
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
1999
|
+
self.len(0, nodes)
|
|
2000
|
+
self.stormIsInErr('Empty block query must be runtsafe', msgs)
|
|
2001
|
+
|
|
2002
|
+
q = '''
|
|
2003
|
+
function foo() {
|
|
2004
|
+
for $x in $lib.range(10) {
|
|
2005
|
+
emit $x
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
for $data in $foo() {
|
|
2010
|
+
if ($data > 10000) {
|
|
2011
|
+
[test:int=$data]
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
|
|
2015
|
+
empty {
|
|
2016
|
+
[test:int=1000]
|
|
2017
|
+
}
|
|
2018
|
+
'''
|
|
2019
|
+
msgs = await core.stormlist(q)
|
|
2020
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
2021
|
+
self.len(1, nodes)
|
|
2022
|
+
self.eq(('test:int', 1000), nodes[0][0])
|
|
2023
|
+
|
|
2024
|
+
q = '''
|
|
2025
|
+
empty {
|
|
2026
|
+
[test:int=12345]
|
|
2027
|
+
}
|
|
2028
|
+
'''
|
|
2029
|
+
idens = [nodes[0][1]['iden'],]
|
|
2030
|
+
msgs = await core.stormlist(q, opts={'idens': idens})
|
|
2031
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
2032
|
+
self.len(1, nodes)
|
|
2033
|
+
self.eq(('test:int', 1000), nodes[0][0])
|
|
2034
|
+
|
|
2035
|
+
q = '''
|
|
2036
|
+
function foo() {
|
|
2037
|
+
empty {
|
|
2038
|
+
$lib.print('foobarbaz')
|
|
2039
|
+
}
|
|
2040
|
+
[test:int=12]
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
yield $foo()
|
|
2044
|
+
empty {
|
|
2045
|
+
$lib.print('neato')
|
|
2046
|
+
}
|
|
2047
|
+
'''
|
|
2048
|
+
msgs = await core.stormlist(q)
|
|
2049
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
2050
|
+
self.len(1, nodes)
|
|
2051
|
+
self.eq(('test:int', 12), nodes[0][0])
|
|
2052
|
+
self.stormIsInPrint('foobarbaz', msgs)
|
|
2053
|
+
self.stormNotInPrint('neato', msgs)
|
|
2054
|
+
|
|
2055
|
+
q = '''
|
|
2056
|
+
function foo() {
|
|
2057
|
+
for $x in $lib.range(2) {
|
|
2058
|
+
emit $x
|
|
2059
|
+
empty {
|
|
2060
|
+
$lib.print(`count is {$x}`)
|
|
2061
|
+
}
|
|
2062
|
+
}
|
|
2063
|
+
}
|
|
2064
|
+
for $x in $foo() {
|
|
2065
|
+
[test:int=$x]
|
|
2066
|
+
}
|
|
2067
|
+
'''
|
|
2068
|
+
msgs = await core.stormlist(q)
|
|
2069
|
+
order = [m[0] for m in msgs]
|
|
2070
|
+
nodes = [m[1] for m in msgs if m[0] == 'node']
|
|
2071
|
+
ndefs = [n[0] for n in nodes]
|
|
2072
|
+
|
|
2073
|
+
self.len(2, nodes)
|
|
2074
|
+
self.eq(order, ['init', 'node:edits', 'node', 'print', 'node:edits', 'node', 'print', 'fini'])
|
|
2075
|
+
self.isin(('test:int', 0), ndefs)
|
|
2076
|
+
self.isin(('test:int', 1), ndefs)
|
|
2077
|
+
|
|
2078
|
+
self.stormIsInPrint('count is 0', msgs)
|
|
2079
|
+
self.stormIsInPrint('count is 1', msgs)
|
|
2080
|
+
|
|
1741
2081
|
async def test_ast_cmdargs(self):
|
|
1742
2082
|
|
|
1743
2083
|
async with self.getTestCore() as core:
|
|
@@ -2527,6 +2867,166 @@ class AstTest(s_test.SynTest):
|
|
|
2527
2867
|
# one for the refs edge (via doedges) and one for the rule..
|
|
2528
2868
|
self.len(2, nodes[1][1]['path']['edges'])
|
|
2529
2869
|
|
|
2870
|
+
async def test_ast_subgraph_caching(self):
|
|
2871
|
+
async with self.getTestCore() as core:
|
|
2872
|
+
limits = (0, 1, 10, 255, 256, 10000)
|
|
2873
|
+
ipv4s = await core.nodes('[inet:ipv4=1.2.3.0/24]')
|
|
2874
|
+
neato = await core.nodes('''[
|
|
2875
|
+
test:str=neato +(refs)> { inet:ipv4 }
|
|
2876
|
+
]''')
|
|
2877
|
+
await core.nodes('[test:str=neato +(selfrefs)> { test:str=neato }]')
|
|
2878
|
+
self.len(1, neato)
|
|
2879
|
+
|
|
2880
|
+
iden = neato[0].iden()
|
|
2881
|
+
idens = [iden,]
|
|
2882
|
+
opts = {
|
|
2883
|
+
'graph': {
|
|
2884
|
+
'degrees': None,
|
|
2885
|
+
'edges': True,
|
|
2886
|
+
'refs': True,
|
|
2887
|
+
'existing': idens
|
|
2888
|
+
},
|
|
2889
|
+
'idens': idens
|
|
2890
|
+
}
|
|
2891
|
+
|
|
2892
|
+
def testedges(msgs):
|
|
2893
|
+
self.len(259, msgs)
|
|
2894
|
+
for m in msgs[:-2]:
|
|
2895
|
+
if m[0] != 'node':
|
|
2896
|
+
continue
|
|
2897
|
+
node = m[1]
|
|
2898
|
+
edges = node[1]['path']['edges']
|
|
2899
|
+
self.len(1, edges)
|
|
2900
|
+
edgeiden, edgedata = edges[0]
|
|
2901
|
+
self.eq(edgeiden, iden)
|
|
2902
|
+
self.true(edgedata.get('reverse', False))
|
|
2903
|
+
self.eq(edgedata['verb'], 'refs')
|
|
2904
|
+
self.eq(edgedata['type'], 'edge')
|
|
2905
|
+
selfref = msgs[-2]
|
|
2906
|
+
node = selfref[1]
|
|
2907
|
+
edges = node[1]['path']['edges']
|
|
2908
|
+
self.len(258, edges)
|
|
2909
|
+
|
|
2910
|
+
for limit in limits:
|
|
2911
|
+
opts['graph']['edgelimit'] = limit
|
|
2912
|
+
msgs = await core.stormlist('tee { --> * } { <-- * }', opts=opts)
|
|
2913
|
+
testedges(msgs)
|
|
2914
|
+
|
|
2915
|
+
burrito = await core.nodes('[test:str=burrito <(awesome)+ { inet:ipv4 }]')
|
|
2916
|
+
self.len(1, burrito)
|
|
2917
|
+
|
|
2918
|
+
iden = burrito[0].iden()
|
|
2919
|
+
for m in msgs:
|
|
2920
|
+
if m[0] != 'node':
|
|
2921
|
+
continue
|
|
2922
|
+
node = m[1]
|
|
2923
|
+
idens.append(node[1]['iden'])
|
|
2924
|
+
|
|
2925
|
+
opts['graph']['existing'] = idens
|
|
2926
|
+
opts['idens'] = [ipv4s[0].iden(),]
|
|
2927
|
+
ipidens = [n.iden() for n in ipv4s]
|
|
2928
|
+
ipidens.append(neato[0].iden())
|
|
2929
|
+
for limit in limits:
|
|
2930
|
+
opts['graph']['edgelimit'] = limit
|
|
2931
|
+
msgs = await core.stormlist('tee { --> * } { <-- * }', opts=opts)
|
|
2932
|
+
self.len(4, msgs)
|
|
2933
|
+
|
|
2934
|
+
node = msgs[1][1]
|
|
2935
|
+
self.eq(node[0], ('test:str', 'burrito'))
|
|
2936
|
+
edges = node[1]['path']['edges']
|
|
2937
|
+
self.len(256, edges)
|
|
2938
|
+
|
|
2939
|
+
for edge in edges:
|
|
2940
|
+
edgeiden, edgedata = edge
|
|
2941
|
+
self.isin(edgeiden, ipidens)
|
|
2942
|
+
self.true(edgedata.get('reverse', False))
|
|
2943
|
+
self.eq(edgedata['verb'], 'awesome')
|
|
2944
|
+
self.eq(edgedata['type'], 'edge')
|
|
2945
|
+
|
|
2946
|
+
node = msgs[2][1]
|
|
2947
|
+
self.eq(node[0], ('test:str', 'neato'))
|
|
2948
|
+
self.len(256, edges)
|
|
2949
|
+
edges = node[1]['path']['edges']
|
|
2950
|
+
for edge in edges:
|
|
2951
|
+
edgeiden, edgedata = edge
|
|
2952
|
+
self.isin(edgeiden, ipidens)
|
|
2953
|
+
self.eq(edgedata['type'], 'edge')
|
|
2954
|
+
if edgedata['verb'] == 'selfrefs':
|
|
2955
|
+
self.eq(edgeiden, neato[0].iden())
|
|
2956
|
+
else:
|
|
2957
|
+
self.eq(edgedata['verb'], 'refs')
|
|
2958
|
+
self.false(edgedata.get('reverse', False))
|
|
2959
|
+
|
|
2960
|
+
opts['graph'].pop('existing', None)
|
|
2961
|
+
opts['idens'] = [neato[0].iden(),]
|
|
2962
|
+
for limit in limits:
|
|
2963
|
+
opts['graph']['edgelimit'] = limit
|
|
2964
|
+
msgs = await core.stormlist('tee { --> * } { <-- * }', opts=opts)
|
|
2965
|
+
selfrefs = 0
|
|
2966
|
+
for m in msgs:
|
|
2967
|
+
if m[0] != 'node':
|
|
2968
|
+
continue
|
|
2969
|
+
|
|
2970
|
+
node = m[1]
|
|
2971
|
+
form = node[0][0]
|
|
2972
|
+
edges = node[1]['path'].get('edges', ())
|
|
2973
|
+
if form == 'inet:ipv4':
|
|
2974
|
+
self.len(0, edges)
|
|
2975
|
+
elif form == 'test:str':
|
|
2976
|
+
self.len(258, edges)
|
|
2977
|
+
for e in edges:
|
|
2978
|
+
self.isin(e[0], ipidens)
|
|
2979
|
+
self.eq('edge', e[1]['type'])
|
|
2980
|
+
if e[0] == neato[0].iden():
|
|
2981
|
+
selfrefs += 1
|
|
2982
|
+
self.eq('selfrefs', e[1]['verb'])
|
|
2983
|
+
else:
|
|
2984
|
+
self.eq('refs', e[1]['verb'])
|
|
2985
|
+
self.eq(selfrefs, 2)
|
|
2986
|
+
|
|
2987
|
+
boop = await core.nodes('[test:str=boop +(refs)> {[inet:ipv4=5.6.7.0/24]}]')
|
|
2988
|
+
await core.nodes('[test:str=boop <(refs)+ {[inet:ipv4=4.5.6.0/24]}]')
|
|
2989
|
+
self.len(1, boop)
|
|
2990
|
+
boopiden = boop[0].iden()
|
|
2991
|
+
opts['idens'] = [boopiden,]
|
|
2992
|
+
for limit in limits:
|
|
2993
|
+
opts['graph']['edgelimit'] = limit
|
|
2994
|
+
msgs = await core.stormlist('tee --join { --> * } { <-- * }', opts=opts)
|
|
2995
|
+
self.len(515, msgs)
|
|
2996
|
+
|
|
2997
|
+
async def test_ast_subgraph_existing_prop_edges(self):
|
|
2998
|
+
|
|
2999
|
+
async with self.getTestCore() as core:
|
|
3000
|
+
(fn,) = await core.nodes('[ file:bytes=(woot,) :md5=e5a23e8a2c0f98850b1a43b595c08e63 ]')
|
|
3001
|
+
fiden = fn.iden()
|
|
3002
|
+
|
|
3003
|
+
rules = {
|
|
3004
|
+
'degrees': None,
|
|
3005
|
+
'edges': True,
|
|
3006
|
+
'refs': True,
|
|
3007
|
+
'existing': [fiden]
|
|
3008
|
+
}
|
|
3009
|
+
|
|
3010
|
+
nodes = []
|
|
3011
|
+
|
|
3012
|
+
async with await core.snap() as snap:
|
|
3013
|
+
async for node, path in snap.storm(':md5 -> hash:md5', opts={'idens': [fiden], 'graph': rules}):
|
|
3014
|
+
nodes.append(node)
|
|
3015
|
+
|
|
3016
|
+
edges = path.metadata.get('edges')
|
|
3017
|
+
self.len(1, edges)
|
|
3018
|
+
self.eq(edges, [
|
|
3019
|
+
[fn.iden(), {
|
|
3020
|
+
"type": "prop",
|
|
3021
|
+
"prop": "md5",
|
|
3022
|
+
"reverse": True
|
|
3023
|
+
}]
|
|
3024
|
+
])
|
|
3025
|
+
|
|
3026
|
+
self.true(path.metadata.get('graph:seed'))
|
|
3027
|
+
|
|
3028
|
+
self.len(1, nodes)
|
|
3029
|
+
|
|
2530
3030
|
async def test_ast_double_init_fini(self):
|
|
2531
3031
|
async with self.getTestCore() as core:
|
|
2532
3032
|
q = '''
|
|
@@ -2618,8 +3118,11 @@ class AstTest(s_test.SynTest):
|
|
|
2618
3118
|
self.len(2, await core.nodes('test:str +#taga*:score'))
|
|
2619
3119
|
self.len(1, await core.nodes('test:str +#tagaa:score=5'))
|
|
2620
3120
|
self.len(1, await core.nodes('test:str +#tagaa:score<(2+4)'))
|
|
3121
|
+
self.len(0, await core.nodes('test:str +#tagaa:score<-5'))
|
|
2621
3122
|
self.len(1, await core.nodes('test:str +#tagaa:score*range=(4,6)'))
|
|
3123
|
+
self.len(0, await core.nodes('test:str +#taga*:score <- *'))
|
|
2622
3124
|
self.len(1, await core.nodes('test:str +#taga*:score <(*)- *'))
|
|
3125
|
+
self.len(3, await core.nodes('test:str +#taga*:score <+(*)- *'))
|
|
2623
3126
|
self.len(2, await core.nodes('$tag=taga* test:str +#$tag:score'))
|
|
2624
3127
|
self.len(1, await core.nodes('$tag=tagaa test:str +#$tag:score=5'))
|
|
2625
3128
|
self.len(1, await core.nodes('$tag=tagaa test:str +#$tag:score*range=(4,6)'))
|
|
@@ -2656,3 +3159,96 @@ class AstTest(s_test.SynTest):
|
|
|
2656
3159
|
|
|
2657
3160
|
with self.raises(s_exc.BadSyntax):
|
|
2658
3161
|
await core.nodes('$tag=taga test:str +#foo.$"tag".$"tag".*:score=2023')
|
|
3162
|
+
|
|
3163
|
+
async def test_ast_righthand_relprop(self):
|
|
3164
|
+
async with self.getTestCore() as core:
|
|
3165
|
+
await core.nodes('''[
|
|
3166
|
+
(test:type10=one :intprop=21 :int2=21)
|
|
3167
|
+
(test:type10=two :intprop=21 :int2=29)
|
|
3168
|
+
(test:float=13.4 :closed=14.0 :open=14.0)
|
|
3169
|
+
(test:float=14.5 :closed=12.0 :open=13.0)
|
|
3170
|
+
(test:float=15.6 :closed=12.0)
|
|
3171
|
+
(test:float=16.7)
|
|
3172
|
+
]''')
|
|
3173
|
+
|
|
3174
|
+
nodes = await core.nodes('test:type10 +(:intprop = :int2)')
|
|
3175
|
+
self.len(1, nodes)
|
|
3176
|
+
self.eq(nodes[0].ndef, ('test:type10', 'one'))
|
|
3177
|
+
|
|
3178
|
+
nodes = await core.nodes('test:float +(:closed = 12.0 and :open)')
|
|
3179
|
+
self.len(1, nodes)
|
|
3180
|
+
self.eq(nodes[0].ndef, ('test:float', 14.5))
|
|
3181
|
+
|
|
3182
|
+
nodes = await core.nodes('test:float +(:open = $lib.null)')
|
|
3183
|
+
self.len(0, nodes)
|
|
3184
|
+
|
|
3185
|
+
nodes = await core.nodes('test:float +(:closed = :open)')
|
|
3186
|
+
self.len(1, nodes)
|
|
3187
|
+
self.eq(nodes[0].ndef, ('test:float', 13.4))
|
|
3188
|
+
|
|
3189
|
+
nodes = await core.nodes('test:float $foobar=:open +(:closed = $foobar)')
|
|
3190
|
+
self.len(1, nodes)
|
|
3191
|
+
self.eq(nodes[0].ndef, ('test:float', 13.4))
|
|
3192
|
+
|
|
3193
|
+
nodes = await core.nodes('test:type10 $foobar=:int2 +(:intprop = $foobar)')
|
|
3194
|
+
self.len(1, nodes)
|
|
3195
|
+
self.eq(nodes[0].ndef, ('test:type10', 'one'))
|
|
3196
|
+
|
|
3197
|
+
async def test_ast_propvalue(self):
|
|
3198
|
+
async with self.getTestCore() as core:
|
|
3199
|
+
|
|
3200
|
+
# Create node with data prop, assign data prop to var, update var
|
|
3201
|
+
q = '[ it:exec:query=(test1,) :opts=({"foo": "bar"}) ] $opts=:opts $opts.bar = "baz"'
|
|
3202
|
+
nodes = await core.nodes(q)
|
|
3203
|
+
self.len(1, nodes)
|
|
3204
|
+
self.eq(nodes[0].props.get('opts'), {'foo': 'bar'})
|
|
3205
|
+
|
|
3206
|
+
q = '[ it:exec:query=(test1,) :opts=({"foo": "bar"}) ] $opts=:opts $opts.bar = "baz" [ :opts=$opts ]'
|
|
3207
|
+
nodes = await core.nodes(q)
|
|
3208
|
+
self.len(1, nodes)
|
|
3209
|
+
self.eq(nodes[0].props.get('opts'), {'foo': 'bar', 'bar': 'baz'})
|
|
3210
|
+
|
|
3211
|
+
q = '''
|
|
3212
|
+
'''
|
|
3213
|
+
msgs = await core.stormlist('[ it:exec:query=(test2,) :opts=({"foo": "bar"}) ]')
|
|
3214
|
+
self.stormHasNoWarnErr(msgs)
|
|
3215
|
+
|
|
3216
|
+
# Lift node with data prop, assign data prop to var, update var
|
|
3217
|
+
q = 'it:exec:query=(test2,) $opts=:opts $opts.bar = "baz"'
|
|
3218
|
+
nodes = await core.nodes(q)
|
|
3219
|
+
self.len(1, nodes)
|
|
3220
|
+
self.eq(nodes[0].props.get('opts'), {'foo': 'bar'})
|
|
3221
|
+
|
|
3222
|
+
q = 'it:exec:query=(test2,) $opts=:opts $opts.bar = "baz" [ :opts=$opts ]'
|
|
3223
|
+
nodes = await core.nodes(q)
|
|
3224
|
+
self.len(1, nodes)
|
|
3225
|
+
self.eq(nodes[0].props.get('opts'), {'foo': 'bar', 'bar': 'baz'})
|
|
3226
|
+
|
|
3227
|
+
# Create node for the lift below
|
|
3228
|
+
q = '''
|
|
3229
|
+
[ it:app:snort:hit=*
|
|
3230
|
+
:flow={[ inet:flow=* :raw=({"foo": "bar"}) ]}
|
|
3231
|
+
]
|
|
3232
|
+
'''
|
|
3233
|
+
nodes = await core.nodes(q)
|
|
3234
|
+
self.len(1, nodes)
|
|
3235
|
+
|
|
3236
|
+
# Lift node, get prop via implicit pivot, assign data prop to var, update var
|
|
3237
|
+
q = f'it:app:snort:hit $raw = :flow::raw $raw.baz="box" | spin | inet:flow'
|
|
3238
|
+
nodes = await core.nodes(q)
|
|
3239
|
+
self.len(1, nodes)
|
|
3240
|
+
self.eq(nodes[0].props.get('raw'), {'foo': 'bar'})
|
|
3241
|
+
|
|
3242
|
+
q = f'it:app:snort:hit $raw = :flow::raw $raw.baz="box" | spin | inet:flow [ :raw=$raw ]'
|
|
3243
|
+
nodes = await core.nodes(q)
|
|
3244
|
+
self.len(1, nodes)
|
|
3245
|
+
self.eq(nodes[0].props.get('raw'), {'foo': 'bar', 'baz': 'box'})
|
|
3246
|
+
|
|
3247
|
+
async def test_ast_subq_runtsafety(self):
|
|
3248
|
+
|
|
3249
|
+
async with self.getTestCore() as core:
|
|
3250
|
+
msgs = await core.stormlist('$foo={[test:str=foo] return($node.value())} $lib.print($foo)')
|
|
3251
|
+
self.stormIsInPrint('foo', msgs)
|
|
3252
|
+
|
|
3253
|
+
msgs = await core.stormlist('$lib.print({[test:str=foo] return($node.value())})')
|
|
3254
|
+
self.stormIsInPrint('foo', msgs)
|