Minor changes to DataSource.apply_common_filters(). Improve overall code coverage.
parent
b1ac24d46e
commit
8ca2c3390b
|
@ -290,28 +290,34 @@ class DataSource(object):
|
|||
for stix_obj in stix_objs:
|
||||
clean = True
|
||||
for filter_ in query:
|
||||
|
||||
# skip filter as filter was identified (when added) as
|
||||
# not a common filter
|
||||
if filter_.field not in STIX_COMMON_FIELDS:
|
||||
continue
|
||||
|
||||
# check filter "field" is in STIX object - if cant be applied
|
||||
# due to STIX object, STIX object is discarded (i.e. did not
|
||||
# make it through the filter)
|
||||
if filter_.field not in stix_obj.keys():
|
||||
clean = False
|
||||
break
|
||||
try:
|
||||
match = getattr(STIXCommonPropertyFilters, filter_.field)(filter_, stix_obj)
|
||||
# skip filter as filter was identified (when added) as
|
||||
# not a common filter
|
||||
if filter_.field not in STIX_COMMON_FIELDS:
|
||||
raise Exception("Error, field: {0} is not supported for filtering on.".format(filter_.field))
|
||||
|
||||
# For properties like granular_markings and external_references
|
||||
# need to break the first property from the string.
|
||||
if "." in filter_.field:
|
||||
field = filter_.field.split(".")[0]
|
||||
else:
|
||||
field = filter_.field
|
||||
|
||||
# check filter "field" is in STIX object - if cant be
|
||||
# applied due to STIX object, STIX object is discarded
|
||||
# (i.e. did not make it through the filter)
|
||||
if field not in stix_obj.keys():
|
||||
clean = False
|
||||
break
|
||||
|
||||
match = getattr(STIXCommonPropertyFilters, field)(filter_, stix_obj)
|
||||
if not match:
|
||||
clean = False
|
||||
break
|
||||
elif match == -1:
|
||||
# error, filter operator not supported for specified field:
|
||||
pass
|
||||
raise Exception("Error, filter operator: {0} not supported for specified field: {1}".format(filter_.op, filter_.field))
|
||||
except Exception as e:
|
||||
print(e)
|
||||
raise ValueError(e)
|
||||
|
||||
# if object unmarked after all filters, add it
|
||||
if clean:
|
||||
|
@ -646,11 +652,11 @@ class STIXCommonPropertyFilters(object):
|
|||
|
||||
@classmethod
|
||||
def modified(cls, filter_, stix_obj):
|
||||
return cls._timestamp(filter_, stix_obj["created"])
|
||||
return cls._timestamp(filter_, stix_obj["modified"])
|
||||
|
||||
@classmethod
|
||||
def object_markings_ref(cls, filter_, stix_obj):
|
||||
for marking_id in stix_obj["object_market_refs"]:
|
||||
def object_marking_refs(cls, filter_, stix_obj):
|
||||
for marking_id in stix_obj["object_marking_refs"]:
|
||||
r = cls._id(filter_, marking_id)
|
||||
if r:
|
||||
return r
|
||||
|
|
|
@ -128,3 +128,19 @@ def test_parse_bundle():
|
|||
assert bundle.objects[0].type == 'indicator'
|
||||
assert bundle.objects[1].type == 'malware'
|
||||
assert bundle.objects[2].type == 'relationship'
|
||||
|
||||
|
||||
def test_parse_unknown_type():
|
||||
unknown = {
|
||||
"type": "other",
|
||||
"id": "other--8e2e2d2b-17d4-4cbf-938f-98ee46b3cd3f",
|
||||
"created": "2016-04-06T20:03:00Z",
|
||||
"modified": "2016-04-06T20:03:00Z",
|
||||
"created_by_ref": "identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
|
||||
"description": "Campaign by Green Group against a series of targets in the financial services sector.",
|
||||
"name": "Green Group Attacks Against Finance",
|
||||
}
|
||||
|
||||
with pytest.raises(stix2.exceptions.ParseError) as excinfo:
|
||||
stix2.parse(unknown)
|
||||
assert str(excinfo.value) == "Can't parse unknown object type 'other'! For custom types, use the CustomObject decorator."
|
||||
|
|
|
@ -135,10 +135,12 @@ def test_custom_no_properties_raises_exception():
|
|||
class NewObject1(object):
|
||||
pass
|
||||
|
||||
|
||||
def test_custom_wrong_properties_arg_raises_exception():
|
||||
with pytest.raises(ValueError):
|
||||
|
||||
@stix2.observables.CustomObservable('x-new-object-type', (("prop", stix2.properties.BooleanProperty())))
|
||||
class NewObject4(object):
|
||||
class NewObject2(object):
|
||||
pass
|
||||
|
||||
|
||||
|
|
|
@ -18,6 +18,109 @@ def collection():
|
|||
return Collection(COLLECTION_URL, MockTAXIIClient())
|
||||
|
||||
|
||||
STIX_OBJS1 = [
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
},
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
},
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.936Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
},
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
},
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
]
|
||||
|
||||
STIX_OBJS2 = [
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-31T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
},
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
},
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def test_ds_smoke():
|
||||
ds1 = DataSource()
|
||||
ds2 = DataSink()
|
||||
|
@ -149,9 +252,21 @@ def test_apply_common_filters():
|
|||
},
|
||||
{
|
||||
"created": "2014-05-08T09:00:00.000Z",
|
||||
"granular_markings": [
|
||||
{
|
||||
"marking_ref": "marking-definition--5e57c739-391a-4eb3-b6be-7d15ca92d5ed",
|
||||
"selectors": [
|
||||
"relationship_type"
|
||||
]
|
||||
}
|
||||
],
|
||||
"id": "relationship--2f9a9aa9-108a-4333-83e2-4fb25add0463",
|
||||
"modified": "2014-05-08T09:00:00.000Z",
|
||||
"object_marking_refs": [
|
||||
"marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9"
|
||||
],
|
||||
"relationship_type": "indicates",
|
||||
"revoked": True,
|
||||
"source_ref": "indicator--a932fcc6-e032-176c-126f-cb970a5a1ade",
|
||||
"target_ref": "malware--fdd60b30-b67c-11e3-b0b9-f01faf20d111",
|
||||
"type": "relationship"
|
||||
|
@ -162,6 +277,13 @@ def test_apply_common_filters():
|
|||
Filter("type", "!=", "relationship"),
|
||||
Filter("id", "=", "relationship--2f9a9aa9-108a-4333-83e2-4fb25add0463"),
|
||||
Filter("labels", "in", "remote-access-trojan"),
|
||||
Filter("created", ">", "2015-01-01T01:00:00.000Z"),
|
||||
Filter("revoked", "=", True),
|
||||
Filter("revoked", "!=", True),
|
||||
Filter("revoked", "?", False),
|
||||
Filter("object_marking_refs", "=", "marking-definition--613f2e26-407d-48c7-9eca-b8e91df99dc9"),
|
||||
Filter("granular_markings.selectors", "in", "relationship_type"),
|
||||
Filter("granular_markings.marking_ref", "=", "marking-definition--5e57c739-391a-4eb3-b6be-7d15ca92d5ed"),
|
||||
]
|
||||
|
||||
ds = DataSource()
|
||||
|
@ -177,108 +299,85 @@ def test_apply_common_filters():
|
|||
resp = ds.apply_common_filters(stix_objs, [filters[2]])
|
||||
assert resp[0]['id'] == stix_objs[0]['id']
|
||||
|
||||
resp = ds.apply_common_filters(stix_objs, [filters[3]])
|
||||
assert resp[0]['id'] == stix_objs[0]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
STIX_OBJS1 = [
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
},
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
},
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.936Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
},
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
},
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
]
|
||||
resp = ds.apply_common_filters(stix_objs, [filters[4]])
|
||||
assert resp[0]['id'] == stix_objs[2]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
STIX_OBJS2 = [
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b9-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-31T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
},
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
},
|
||||
{
|
||||
"created": "2017-01-27T13:49:53.935Z",
|
||||
"id": "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f",
|
||||
"labels": [
|
||||
"url-watchlist"
|
||||
],
|
||||
"modified": "2017-01-27T13:49:53.935Z",
|
||||
"name": "Malicious site hosting downloader",
|
||||
"pattern": "[url:value = 'http://x4z9arb.cn/4712']",
|
||||
"type": "indicator",
|
||||
"valid_from": "2017-01-27T13:49:53.935382Z"
|
||||
}
|
||||
]
|
||||
# Note that if 'revoked' property is not present in object.
|
||||
# Currently we can't use such an expression to filter for...
|
||||
resp = ds.apply_common_filters(stix_objs, [filters[5]])
|
||||
assert len(resp) == 0
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
ds.apply_common_filters(stix_objs, [filters[6]])
|
||||
|
||||
assert str(excinfo.value) == ("Error, filter operator: {0} not supported "
|
||||
"for specified field: {1}").format(filters[6].op,
|
||||
filters[6].field)
|
||||
|
||||
resp = ds.apply_common_filters(stix_objs, [filters[7]])
|
||||
assert resp[0]['id'] == stix_objs[2]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
resp = ds.apply_common_filters(stix_objs, [filters[8], filters[9]])
|
||||
assert resp[0]['id'] == stix_objs[2]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
# These are used with STIX_OBJS2
|
||||
more_filters = [
|
||||
Filter("modified", "<", "2017-01-28T13:49:53.935Z"),
|
||||
Filter("modified", ">", "2017-01-28T13:49:53.935Z"),
|
||||
Filter("modified", ">=", "2017-01-27T13:49:53.935Z"),
|
||||
Filter("modified", "<=", "2017-01-27T13:49:53.935Z"),
|
||||
Filter("modified", "?", "2017-01-27T13:49:53.935Z"),
|
||||
Filter("id", "!=", "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f"),
|
||||
Filter("id", "?", "indicator--d81f86b8-975b-bc0b-775e-810c5ad45a4f"),
|
||||
Filter("notacommonproperty", "=", "bar"),
|
||||
]
|
||||
|
||||
resp = ds.apply_common_filters(STIX_OBJS2, [more_filters[0]])
|
||||
assert resp[0]['id'] == STIX_OBJS2[1]['id']
|
||||
assert len(resp) == 2
|
||||
|
||||
resp = ds.apply_common_filters(STIX_OBJS2, [more_filters[1]])
|
||||
assert resp[0]['id'] == STIX_OBJS2[0]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
resp = ds.apply_common_filters(STIX_OBJS2, [more_filters[2]])
|
||||
assert resp[0]['id'] == STIX_OBJS2[0]['id']
|
||||
assert len(resp) == 3
|
||||
|
||||
resp = ds.apply_common_filters(STIX_OBJS2, [more_filters[3]])
|
||||
assert resp[0]['id'] == STIX_OBJS2[1]['id']
|
||||
assert len(resp) == 2
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
ds.apply_common_filters(STIX_OBJS2, [more_filters[4]])
|
||||
|
||||
assert str(excinfo.value) == ("Error, filter operator: {0} not supported "
|
||||
"for specified field: {1}").format(more_filters[4].op,
|
||||
more_filters[4].field)
|
||||
|
||||
resp = ds.apply_common_filters(STIX_OBJS2, [more_filters[5]])
|
||||
assert resp[0]['id'] == STIX_OBJS2[0]['id']
|
||||
assert len(resp) == 1
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
ds.apply_common_filters(STIX_OBJS2, [more_filters[6]])
|
||||
|
||||
assert str(excinfo.value) == ("Error, filter operator: {0} not supported "
|
||||
"for specified field: {1}").format(more_filters[6].op,
|
||||
more_filters[6].field)
|
||||
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
ds.apply_common_filters(STIX_OBJS2, [more_filters[7]])
|
||||
|
||||
assert str(excinfo.value) == ("Error, field: {0} is not supported for "
|
||||
"filtering on.".format(more_filters[7].field))
|
||||
|
||||
|
||||
def test_deduplicate():
|
||||
|
|
|
@ -209,7 +209,8 @@ def test_registered_custom_marking():
|
|||
|
||||
|
||||
def test_not_registered_marking_raises_exception():
|
||||
with pytest.raises(ValueError):
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
# Used custom object on purpose to demonstrate a not-registered marking
|
||||
@stix2.sdo.CustomObject('x-new-marking-type2', [
|
||||
('property1', stix2.properties.StringProperty(required=True)),
|
||||
('property2', stix2.properties.IntegerProperty()),
|
||||
|
@ -227,12 +228,17 @@ def test_not_registered_marking_raises_exception():
|
|||
definition=no
|
||||
)
|
||||
|
||||
assert str(excinfo.value) == "definition_type must be a valid marking type"
|
||||
|
||||
def test_bad_marking_construction():
|
||||
with pytest.raises(ValueError):
|
||||
@stix2.sdo.CustomObject('x-new-marking-type2', ("a", "b"))
|
||||
|
||||
def test_marking_wrong_type_construction():
|
||||
with pytest.raises(ValueError) as excinfo:
|
||||
# Test passing wrong type for properties.
|
||||
@stix2.CustomMarking('x-new-marking-type2', ("a", "b"))
|
||||
class NewObject3(object):
|
||||
pass
|
||||
|
||||
assert str(excinfo.value) == "Must supply a list, containing tuples. For example, [('property1', IntegerProperty())]"
|
||||
|
||||
|
||||
# TODO: Add other examples
|
||||
|
|
|
@ -8,6 +8,8 @@ import stix2
|
|||
|
||||
from .constants import OBSERVED_DATA_ID
|
||||
|
||||
OBJECTS_REGEX = re.compile('\"objects\": {(?:.*?)(?:(?:[^{]*?)|(?:{[^{]*?}))*}', re.DOTALL)
|
||||
|
||||
|
||||
EXPECTED = """{
|
||||
"type": "observed-data",
|
||||
|
@ -173,7 +175,7 @@ def test_parse_observed_data(data):
|
|||
}""",
|
||||
])
|
||||
def test_parse_artifact_valid(data):
|
||||
odata_str = re.compile('\"objects\": {(?:.*?)(?:(?:[^{]*?)|(?:{[^{]*?}))*}', re.DOTALL).sub('"objects": { %s }' % data, EXPECTED)
|
||||
odata_str = OBJECTS_REGEX.sub('"objects": { %s }' % data, EXPECTED)
|
||||
odata = stix2.parse(odata_str)
|
||||
assert odata.objects["0"].type == "artifact"
|
||||
|
||||
|
@ -194,7 +196,7 @@ def test_parse_artifact_valid(data):
|
|||
}""",
|
||||
])
|
||||
def test_parse_artifact_invalid(data):
|
||||
odata_str = re.compile('\"objects\": {(?:.*?)(?:(?:[^{]*?)|(?:{[^{]*?}))*}', re.DOTALL).sub('"objects": { %s }' % data, EXPECTED)
|
||||
odata_str = OBJECTS_REGEX.sub('"objects": { %s }' % data, EXPECTED)
|
||||
with pytest.raises(ValueError):
|
||||
stix2.parse(odata_str)
|
||||
|
||||
|
@ -204,6 +206,7 @@ def test_artifact_example_dependency_error():
|
|||
stix2.Artifact(url="http://example.com/sirvizio.exe")
|
||||
|
||||
assert excinfo.value.dependencies == [("hashes", "url")]
|
||||
assert str(excinfo.value) == "The property dependencies for Artifact: (hashes, url) are not met."
|
||||
|
||||
|
||||
@pytest.mark.parametrize("data", [
|
||||
|
@ -215,7 +218,7 @@ def test_artifact_example_dependency_error():
|
|||
}""",
|
||||
])
|
||||
def test_parse_autonomous_system_valid(data):
|
||||
odata_str = re.compile('\"objects\": {(?:.*?)(?:(?:[^{]*?)|(?:{[^{]*?}))*}', re.DOTALL).sub('"objects": { %s }' % data, EXPECTED)
|
||||
odata_str = OBJECTS_REGEX.sub('"objects": { %s }' % data, EXPECTED)
|
||||
odata = stix2.parse(odata_str)
|
||||
assert odata.objects["0"].type == "autonomous-system"
|
||||
assert odata.objects["0"].number == 15139
|
||||
|
@ -358,7 +361,7 @@ def test_parse_email_message_not_multipart(data):
|
|||
}""",
|
||||
])
|
||||
def test_parse_file_archive(data):
|
||||
odata_str = re.compile('\"objects\": {(?:.*?)(?:(?:[^{]*?)|(?:{[^{]*?}))*}', re.DOTALL).sub('"objects": { %s }' % data, EXPECTED)
|
||||
odata_str = OBJECTS_REGEX.sub('"objects": { %s }' % data, EXPECTED)
|
||||
odata = stix2.parse(odata_str)
|
||||
assert odata.objects["3"].extensions['archive-ext'].version == "5.0"
|
||||
|
||||
|
@ -555,6 +558,7 @@ def test_artifact_mutual_exclusion_error():
|
|||
|
||||
assert excinfo.value.cls == stix2.Artifact
|
||||
assert excinfo.value.properties == ["payload_bin", "url"]
|
||||
assert str(excinfo.value) == "The (payload_bin, url) properties for Artifact are mutually exclusive."
|
||||
|
||||
|
||||
def test_directory_example():
|
||||
|
@ -925,6 +929,10 @@ def test_process_example_empty_error():
|
|||
properties_of_process = list(stix2.Process._properties.keys())
|
||||
properties_of_process.remove("type")
|
||||
assert excinfo.value.properties == sorted(properties_of_process)
|
||||
msg = "At least one of the ({1}) properties for {0} must be populated."
|
||||
msg = msg.format(stix2.Process.__name__,
|
||||
", ".join(sorted(properties_of_process)))
|
||||
assert str(excinfo.value) == msg
|
||||
|
||||
|
||||
def test_process_example_empty_with_extensions():
|
||||
|
|
|
@ -206,15 +206,22 @@ def test_dictionary_property_valid(d):
|
|||
|
||||
|
||||
@pytest.mark.parametrize("d", [
|
||||
{'a': 'something'},
|
||||
{'a'*300: 'something'},
|
||||
{'Hey!': 'something'},
|
||||
[{'a': 'something'}, "Invalid dictionary key a: (shorter than 3 characters)."],
|
||||
[{'a'*300: 'something'}, "Invalid dictionary key aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
||||
"aaaaaaaaaaaaaaaaaaaaaaa: (longer than 256 characters)."],
|
||||
[{'Hey!': 'something'}, "Invalid dictionary key Hey!: (contains characters other thanlowercase a-z, "
|
||||
"uppercase A-Z, numerals 0-9, hyphen (-), or underscore (_))."],
|
||||
])
|
||||
def test_dictionary_property_invalid(d):
|
||||
dict_prop = DictionaryProperty()
|
||||
|
||||
with pytest.raises(DictionaryKeyError):
|
||||
dict_prop.clean(d)
|
||||
with pytest.raises(DictionaryKeyError) as excinfo:
|
||||
dict_prop.clean(d[0])
|
||||
|
||||
assert str(excinfo.value) == d[1]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("value", [
|
||||
|
|
|
@ -128,6 +128,11 @@ def test_versioning_error_bad_modified_value():
|
|||
assert excinfo.value.prop_name == "modified"
|
||||
assert excinfo.value.reason == "The new modified datetime cannot be before the current modified datatime."
|
||||
|
||||
msg = "Invalid value for {0} '{1}': {2}"
|
||||
msg = msg.format(stix2.Campaign.__name__, "modified",
|
||||
"The new modified datetime cannot be before the current modified datatime.")
|
||||
assert str(excinfo.value) == msg
|
||||
|
||||
|
||||
def test_versioning_error_usetting_required_property():
|
||||
campaign_v1 = stix2.Campaign(
|
||||
|
@ -145,6 +150,10 @@ def test_versioning_error_usetting_required_property():
|
|||
assert excinfo.value.cls == stix2.Campaign
|
||||
assert excinfo.value.properties == ["name"]
|
||||
|
||||
msg = "No values for required properties for {0}: ({1})."
|
||||
msg = msg.format(stix2.Campaign.__name__, "name")
|
||||
assert str(excinfo.value) == msg
|
||||
|
||||
|
||||
def test_versioning_error_new_version_of_revoked():
|
||||
campaign_v1 = stix2.Campaign(
|
||||
|
@ -162,6 +171,7 @@ def test_versioning_error_new_version_of_revoked():
|
|||
campaign_v2.new_version(name="barney")
|
||||
|
||||
assert excinfo.value.called_by == "new_version"
|
||||
assert str(excinfo.value) == "Cannot create a new version of a revoked object."
|
||||
|
||||
|
||||
def test_versioning_error_revoke_of_revoked():
|
||||
|
@ -180,3 +190,4 @@ def test_versioning_error_revoke_of_revoked():
|
|||
campaign_v2.revoke()
|
||||
|
||||
assert excinfo.value.called_by == "revoke"
|
||||
assert str(excinfo.value) == "Cannot revoke an already revoked object."
|
||||
|
|
Loading…
Reference in New Issue