Increase code coverage
parent
6fa3c84aa3
commit
0cd75e3fba
|
@ -121,7 +121,7 @@ class DependentPropertiesError(STIXError, TypeError):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
msg = "The property dependencies for {0}: ({1}) are not met."
|
msg = "The property dependencies for {0}: ({1}) are not met."
|
||||||
return msg.format(self.cls.__name__,
|
return msg.format(self.cls.__name__,
|
||||||
", ".join(x for x in self.dependencies))
|
", ".join(x for x, y in self.dependencies))
|
||||||
|
|
||||||
|
|
||||||
class AtLeastOnePropertyError(STIXError, TypeError):
|
class AtLeastOnePropertyError(STIXError, TypeError):
|
||||||
|
|
|
@ -118,6 +118,20 @@ def test_create_bundle_with_arg_listarg_and_kwarg(indicator, malware, relationsh
|
||||||
assert str(bundle) == EXPECTED_BUNDLE
|
assert str(bundle) == EXPECTED_BUNDLE
|
||||||
|
|
||||||
|
|
||||||
|
def test_create_bundle_invalid(indicator, malware, relationship):
|
||||||
|
with pytest.raises(ValueError) as excinfo:
|
||||||
|
stix2.Bundle(objects=[1])
|
||||||
|
assert excinfo.value.reason == "This property may only contain a dictionary or object"
|
||||||
|
|
||||||
|
with pytest.raises(ValueError) as excinfo:
|
||||||
|
stix2.Bundle(objects=[{}])
|
||||||
|
assert excinfo.value.reason == "This property may only contain a non-empty dictionary or object"
|
||||||
|
|
||||||
|
with pytest.raises(ValueError) as excinfo:
|
||||||
|
stix2.Bundle(objects=[{'type': 'bundle'}])
|
||||||
|
assert excinfo.value.reason == 'This property may not contain a Bundle object'
|
||||||
|
|
||||||
|
|
||||||
def test_parse_bundle():
|
def test_parse_bundle():
|
||||||
bundle = stix2.parse(EXPECTED_BUNDLE)
|
bundle = stix2.parse(EXPECTED_BUNDLE)
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,19 @@ def test_parse_custom_object_type():
|
||||||
assert nt.property1 == 'something'
|
assert nt.property1 == 'something'
|
||||||
|
|
||||||
|
|
||||||
|
def test_parse_unregistered_custom_object_type():
|
||||||
|
nt_string = """{
|
||||||
|
"type": "x-foobar-observable",
|
||||||
|
"created": "2015-12-21T19:59:11Z",
|
||||||
|
"property1": "something"
|
||||||
|
}"""
|
||||||
|
|
||||||
|
with pytest.raises(stix2.exceptions.ParseError) as excinfo:
|
||||||
|
stix2.parse(nt_string)
|
||||||
|
assert "Can't parse unknown object type" in str(excinfo.value)
|
||||||
|
assert "use the CustomObject decorator." in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
@stix2.observables.CustomObservable('x-new-observable', {
|
@stix2.observables.CustomObservable('x-new-observable', {
|
||||||
'property1': stix2.properties.StringProperty(required=True),
|
'property1': stix2.properties.StringProperty(required=True),
|
||||||
'property2': stix2.properties.IntegerProperty(),
|
'property2': stix2.properties.IntegerProperty(),
|
||||||
|
@ -139,6 +152,36 @@ def test_custom_observable_object():
|
||||||
assert "'property2' is too small." in str(excinfo.value)
|
assert "'property2' is too small." in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_observable_object_invalid_ref_property():
|
||||||
|
@stix2.observables.CustomObservable('x-new-obs', {
|
||||||
|
'property1': stix2.properties.StringProperty(required=True),
|
||||||
|
'property_ref': stix2.properties.StringProperty(),
|
||||||
|
})
|
||||||
|
class NewObs():
|
||||||
|
pass
|
||||||
|
|
||||||
|
with pytest.raises(ValueError) as excinfo:
|
||||||
|
NewObs(_valid_refs={'1': 'file'},
|
||||||
|
property1='something',
|
||||||
|
property_ref='1')
|
||||||
|
assert "is named like an object reference property but is not an ObjectReferenceProperty" in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
|
def test_custom_observable_object_invalid_valid_refs():
|
||||||
|
@stix2.observables.CustomObservable('x-new-obs', {
|
||||||
|
'property1': stix2.properties.StringProperty(required=True),
|
||||||
|
'property_ref': stix2.properties.ObjectReferenceProperty(valid_types='email-addr'),
|
||||||
|
})
|
||||||
|
class NewObs():
|
||||||
|
pass
|
||||||
|
|
||||||
|
with pytest.raises(Exception) as excinfo:
|
||||||
|
NewObs(_valid_refs=['1'],
|
||||||
|
property1='something',
|
||||||
|
property_ref='1')
|
||||||
|
assert "must be created with _valid_refs as a dict, not a list" in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
def test_parse_custom_observable_object():
|
def test_parse_custom_observable_object():
|
||||||
nt_string = """{
|
nt_string = """{
|
||||||
"type": "x-new-observable",
|
"type": "x-new-observable",
|
||||||
|
|
|
@ -125,6 +125,42 @@ def test_observed_data_example_with_bad_refs():
|
||||||
assert excinfo.value.reason == "Invalid object reference for 'Directory:contains_refs': '2' is not a valid object in local scope"
|
assert excinfo.value.reason == "Invalid object reference for 'Directory:contains_refs': '2' is not a valid object in local scope"
|
||||||
|
|
||||||
|
|
||||||
|
def test_observed_data_example_with_non_dictionary():
|
||||||
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
|
stix2.ObservedData(
|
||||||
|
id="observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
|
||||||
|
created_by_ref="identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
|
||||||
|
created="2016-04-06T19:58:16.000Z",
|
||||||
|
modified="2016-04-06T19:58:16.000Z",
|
||||||
|
first_observed="2015-12-21T19:00:00Z",
|
||||||
|
last_observed="2015-12-21T19:00:00Z",
|
||||||
|
number_observed=50,
|
||||||
|
objects="file: foo.exe",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.ObservedData
|
||||||
|
assert excinfo.value.prop_name == "objects"
|
||||||
|
assert 'must contain a dictionary' in excinfo.value.reason
|
||||||
|
|
||||||
|
|
||||||
|
def test_observed_data_example_with_empty_dictionary():
|
||||||
|
with pytest.raises(stix2.exceptions.InvalidValueError) as excinfo:
|
||||||
|
stix2.ObservedData(
|
||||||
|
id="observed-data--b67d30ff-02ac-498a-92f9-32f845f448cf",
|
||||||
|
created_by_ref="identity--f431f809-377b-45e0-aa1c-6a4751cae5ff",
|
||||||
|
created="2016-04-06T19:58:16.000Z",
|
||||||
|
modified="2016-04-06T19:58:16.000Z",
|
||||||
|
first_observed="2015-12-21T19:00:00Z",
|
||||||
|
last_observed="2015-12-21T19:00:00Z",
|
||||||
|
number_observed=50,
|
||||||
|
objects={},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert excinfo.value.cls == stix2.ObservedData
|
||||||
|
assert excinfo.value.prop_name == "objects"
|
||||||
|
assert 'must contain a non-empty dictionary' in excinfo.value.reason
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("data", [
|
@pytest.mark.parametrize("data", [
|
||||||
EXPECTED,
|
EXPECTED,
|
||||||
{
|
{
|
||||||
|
@ -416,6 +452,8 @@ def test_parse_email_message_with_at_least_one_error(data):
|
||||||
|
|
||||||
assert excinfo.value.cls == stix2.EmailMIMEComponent
|
assert excinfo.value.cls == stix2.EmailMIMEComponent
|
||||||
assert excinfo.value.properties == ["body", "body_raw_ref"]
|
assert excinfo.value.properties == ["body", "body_raw_ref"]
|
||||||
|
assert "At least one of the" in str(excinfo.value)
|
||||||
|
assert "must be populated" in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("data", [
|
@pytest.mark.parametrize("data", [
|
||||||
|
@ -555,6 +593,7 @@ def test_artifact_mutual_exclusion_error():
|
||||||
|
|
||||||
assert excinfo.value.cls == stix2.Artifact
|
assert excinfo.value.cls == stix2.Artifact
|
||||||
assert excinfo.value.properties == ["payload_bin", "url"]
|
assert excinfo.value.properties == ["payload_bin", "url"]
|
||||||
|
assert 'are mutually exclusive' in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
def test_directory_example():
|
def test_directory_example():
|
||||||
|
@ -800,6 +839,8 @@ def test_file_example_encryption_error():
|
||||||
|
|
||||||
assert excinfo.value.cls == stix2.File
|
assert excinfo.value.cls == stix2.File
|
||||||
assert excinfo.value.dependencies == [("is_encrypted", "encryption_algorithm")]
|
assert excinfo.value.dependencies == [("is_encrypted", "encryption_algorithm")]
|
||||||
|
assert "property dependencies" in str(excinfo.value)
|
||||||
|
assert "are not met" in str(excinfo.value)
|
||||||
|
|
||||||
with pytest.raises(stix2.exceptions.DependentPropertiesError) as excinfo:
|
with pytest.raises(stix2.exceptions.DependentPropertiesError) as excinfo:
|
||||||
stix2.File(name="qwerty.dll",
|
stix2.File(name="qwerty.dll",
|
||||||
|
|
|
@ -5,10 +5,10 @@ from stix2.exceptions import AtLeastOnePropertyError, DictionaryKeyError
|
||||||
from stix2.observables import EmailMIMEComponent, ExtensionsProperty
|
from stix2.observables import EmailMIMEComponent, ExtensionsProperty
|
||||||
from stix2.properties import (BinaryProperty, BooleanProperty,
|
from stix2.properties import (BinaryProperty, BooleanProperty,
|
||||||
DictionaryProperty, EmbeddedObjectProperty,
|
DictionaryProperty, EmbeddedObjectProperty,
|
||||||
EnumProperty, HashesProperty, HexProperty,
|
EnumProperty, FloatProperty, HashesProperty,
|
||||||
IDProperty, IntegerProperty, ListProperty,
|
HexProperty, IDProperty, IntegerProperty,
|
||||||
Property, ReferenceProperty, StringProperty,
|
ListProperty, Property, ReferenceProperty,
|
||||||
TimestampProperty, TypeProperty)
|
StringProperty, TimestampProperty, TypeProperty)
|
||||||
|
|
||||||
from .constants import FAKE_TIME
|
from .constants import FAKE_TIME
|
||||||
|
|
||||||
|
@ -119,6 +119,27 @@ def test_integer_property_invalid(value):
|
||||||
int_prop.clean(value)
|
int_prop.clean(value)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("value", [
|
||||||
|
2,
|
||||||
|
-1,
|
||||||
|
3.14,
|
||||||
|
False,
|
||||||
|
])
|
||||||
|
def test_float_property_valid(value):
|
||||||
|
int_prop = FloatProperty()
|
||||||
|
assert int_prop.clean(value) is not None
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("value", [
|
||||||
|
"something",
|
||||||
|
StringProperty(),
|
||||||
|
])
|
||||||
|
def test_float_property_invalid(value):
|
||||||
|
int_prop = FloatProperty()
|
||||||
|
with pytest.raises(ValueError):
|
||||||
|
int_prop.clean(value)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("value", [
|
@pytest.mark.parametrize("value", [
|
||||||
True,
|
True,
|
||||||
False,
|
False,
|
||||||
|
@ -210,10 +231,22 @@ def test_dictionary_property_valid(d):
|
||||||
{'a'*300: 'something'},
|
{'a'*300: 'something'},
|
||||||
{'Hey!': 'something'},
|
{'Hey!': 'something'},
|
||||||
])
|
])
|
||||||
|
def test_dictionary_property_invalid_key(d):
|
||||||
|
dict_prop = DictionaryProperty()
|
||||||
|
|
||||||
|
with pytest.raises(DictionaryKeyError) as excinfo:
|
||||||
|
dict_prop.clean(d)
|
||||||
|
assert "Invalid dictionary key" in str(excinfo.value)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("d", [
|
||||||
|
{},
|
||||||
|
"{'description': 'something'}",
|
||||||
|
])
|
||||||
def test_dictionary_property_invalid(d):
|
def test_dictionary_property_invalid(d):
|
||||||
dict_prop = DictionaryProperty()
|
dict_prop = DictionaryProperty()
|
||||||
|
|
||||||
with pytest.raises(DictionaryKeyError):
|
with pytest.raises(ValueError):
|
||||||
dict_prop.clean(d)
|
dict_prop.clean(d)
|
||||||
|
|
||||||
|
|
||||||
|
@ -250,10 +283,18 @@ def test_embedded_property():
|
||||||
emb_prop.clean("string")
|
emb_prop.clean("string")
|
||||||
|
|
||||||
|
|
||||||
def test_enum_property():
|
@pytest.mark.parametrize("value", [
|
||||||
enum_prop = EnumProperty(['a', 'b', 'c'])
|
['a', 'b', 'c'],
|
||||||
|
('a', 'b', 'c'),
|
||||||
|
'b',
|
||||||
|
])
|
||||||
|
def test_enum_property_valid(value):
|
||||||
|
enum_prop = EnumProperty(value)
|
||||||
assert enum_prop.clean('b')
|
assert enum_prop.clean('b')
|
||||||
|
|
||||||
|
|
||||||
|
def test_enum_property_invalid():
|
||||||
|
enum_prop = EnumProperty(['a', 'b', 'c'])
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
enum_prop.clean('z')
|
enum_prop.clean('z')
|
||||||
|
|
||||||
|
|
|
@ -160,6 +160,7 @@ def test_versioning_error_new_version_of_revoked():
|
||||||
|
|
||||||
with pytest.raises(stix2.exceptions.RevokeError) as excinfo:
|
with pytest.raises(stix2.exceptions.RevokeError) as excinfo:
|
||||||
campaign_v2.new_version(name="barney")
|
campaign_v2.new_version(name="barney")
|
||||||
|
assert str(excinfo.value) == "Cannot create a new version of a revoked object."
|
||||||
|
|
||||||
assert excinfo.value.called_by == "new_version"
|
assert excinfo.value.called_by == "new_version"
|
||||||
|
|
||||||
|
@ -178,5 +179,6 @@ def test_versioning_error_revoke_of_revoked():
|
||||||
|
|
||||||
with pytest.raises(stix2.exceptions.RevokeError) as excinfo:
|
with pytest.raises(stix2.exceptions.RevokeError) as excinfo:
|
||||||
campaign_v2.revoke()
|
campaign_v2.revoke()
|
||||||
|
assert str(excinfo.value) == "Cannot revoke an already revoked object."
|
||||||
|
|
||||||
assert excinfo.value.called_by == "revoke"
|
assert excinfo.value.called_by == "revoke"
|
||||||
|
|
Loading…
Reference in New Issue