import pytest from stix2.exceptions import DictionaryKeyError from stix2.properties import (BinaryProperty, BooleanProperty, DictionaryProperty, HashesProperty, HexProperty, IDProperty, IntegerProperty, ListProperty, Property, ReferenceProperty, StringProperty, TimestampProperty, TypeProperty) from .constants import FAKE_TIME def test_property(): p = Property() assert p.required is False def test_basic_clean(): class Prop(Property): def clean(self, value): if value == 42: return value else: raise ValueError("Must be 42") p = Prop() assert p.clean(42) == 42 with pytest.raises(ValueError): p.clean(41) def test_default_field(): class Prop(Property): def default(self): return 77 p = Prop() assert p.default() == 77 def test_fixed_property(): p = Property(fixed="2.0") assert p.clean("2.0") with pytest.raises(ValueError): assert p.clean("x") is False with pytest.raises(ValueError): assert p.clean(2.0) is False assert p.default() == "2.0" assert p.clean(p.default()) def test_list_property(): p = ListProperty(StringProperty) assert p.clean(['abc', 'xyz']) with pytest.raises(ValueError): p.clean([]) def test_string_property(): prop = StringProperty() assert prop.clean('foobar') assert prop.clean(1) assert prop.clean([1, 2, 3]) def test_type_property(): prop = TypeProperty('my-type') assert prop.clean('my-type') with pytest.raises(ValueError): prop.clean('not-my-type') assert prop.clean(prop.default()) def test_id_property(): idprop = IDProperty('my-type') assert idprop.clean('my-type--90aaca8a-1110-5d32-956d-ac2f34a1bd8c') with pytest.raises(ValueError) as excinfo: idprop.clean('not-my-type--90aaca8a-1110-5d32-956d-ac2f34a1bd8c') assert str(excinfo.value) == "must start with 'my-type--'." with pytest.raises(ValueError) as excinfo: idprop.clean('my-type--foo') assert str(excinfo.value) == "must have a valid UUID after the prefix." assert idprop.clean(idprop.default()) @pytest.mark.parametrize("value", [ 2, -1, 3.14, False, ]) def test_integer_property_valid(value): int_prop = IntegerProperty() assert int_prop.clean(value) is not None @pytest.mark.parametrize("value", [ "something", StringProperty(), ]) def test_integer_property_invalid(value): int_prop = IntegerProperty() with pytest.raises(ValueError): int_prop.clean(value) @pytest.mark.parametrize("value", [ True, False, 'True', 'False', 'true', 'false', 'TRUE', 'FALSE', 'T', 'F', 't', 'f', 1, 0, ]) def test_boolean_property_valid(value): bool_prop = BooleanProperty() assert bool_prop.clean(value) is not None @pytest.mark.parametrize("value", [ 'abc', ['false'], {'true': 'true'}, 2, -1, ]) def test_boolean_property_invalid(value): bool_prop = BooleanProperty() with pytest.raises(ValueError): bool_prop.clean(value) def test_reference_property(): ref_prop = ReferenceProperty() assert ref_prop.clean("my-type--3a331bfe-0566-55e1-a4a0-9a2cd355a300") with pytest.raises(ValueError): ref_prop.clean("foo") @pytest.mark.parametrize("value", [ '2017-01-01T12:34:56Z', '2017-01-01 12:34:56', 'Jan 1 2017 12:34:56', ]) def test_timestamp_property_valid(value): ts_prop = TimestampProperty() assert ts_prop.clean(value) == FAKE_TIME def test_timestamp_property_invalid(): ts_prop = TimestampProperty() with pytest.raises(ValueError): ts_prop.clean(1) with pytest.raises(ValueError): ts_prop.clean("someday sometime") def test_binary_property(): bin_prop = BinaryProperty() assert bin_prop.clean("TG9yZW0gSXBzdW0=") with pytest.raises(ValueError): bin_prop.clean("foobar") def test_hex_property(): hex_prop = HexProperty() assert hex_prop.clean("4c6f72656d20497073756d") with pytest.raises(ValueError): hex_prop.clean("foobar") @pytest.mark.parametrize("d", [ {'description': 'something'}, [('abc', 1), ('bcd', 2), ('cde', 3)], ]) def test_dictionary_property_valid(d): dict_prop = DictionaryProperty() assert dict_prop.clean(d) @pytest.mark.parametrize("d", [ {'a': 'something'}, {'a'*300: 'something'}, {'Hey!': 'something'}, ]) def test_dictionary_property_invalid(d): dict_prop = DictionaryProperty() with pytest.raises(DictionaryKeyError): dict_prop.clean(d) @pytest.mark.parametrize("value", [ {"sha256": "6db12788c37247f2316052e142f42f4b259d6561751e5f401a1ae2a6df9c674b"}, [('MD5', '2dfb1bcc980200c6706feee399d41b3f'), ('RIPEMD-160', 'b3a8cd8a27c90af79b3c81754f267780f443dfef')], ]) def test_hashes_property_valid(value): hash_prop = HashesProperty() assert hash_prop.clean(value) @pytest.mark.parametrize("value", [ {"MD5": "a"}, {"SHA-256": "2dfb1bcc980200c6706feee399d41b3f"}, ]) def test_hashes_property_invalid(value): hash_prop = HashesProperty() with pytest.raises(ValueError): hash_prop.clean(value)