def test_superset_blacklist(self):
     """
     Verify correct behavior when blacklist contains all type codes.
     """
     blacklist = "".join(_CODES)
     with self.assertRaises(errors.InvalidArgument):
         dbus_signatures(blacklist=blacklist)
def dbus_signature_strategy(draw):
    """
    Generates any valid dbus signature strategy.
    """
    max_codes = draw(strategies.integers(min_value=1, max_value=5))
    min_complete_types = draw(strategies.integers(min_value=0, max_value=5))
    max_complete_types = draw(
        strategies.one_of(
            strategies.integers(min_value=min_complete_types, max_value=5),
            strategies.none(),
        )
    )
    min_struct_len = draw(strategies.integers(min_value=1, max_value=5))
    max_struct_len = draw(
        strategies.one_of(
            strategies.integers(min_value=min_struct_len, max_value=5),
            strategies.none(),
        )
    )
    blacklist_chars = strategies.frozensets(
        elements=strategies.sampled_from(_CODES), max_size=len(_CODES) - 1
    )
    blacklist = draw(strategies.none() | blacklist_chars.map("".join))

    return dbus_signatures(
        max_codes=max_codes,
        min_complete_types=min_complete_types,
        max_complete_types=max_complete_types,
        min_struct_len=min_struct_len,
        max_struct_len=max_struct_len,
        exclude_arrays=not draw(strategies.booleans()),
        exclude_dicts=not draw(strategies.booleans()),
        exclude_structs=not draw(strategies.booleans()),
        blacklist=blacklist,
    )
def signal_arg_strategy(*,
                        min_children=0,
                        max_children=None,
                        dbus_signature_args=None):
    """
    Build a strategy to generate data for an introspection arg for signals.

    :param min_children: the minimum number of child elements
    :type min_children: non-negative int
    :param max_children: the maximum number of child elements
    :type max_children: non-negative int or None
    :param dbus_signature_args: to override dbus_signatures defaults
    :type dbus_signature_args: dict of str * object or NoneType
    """
    return builds(
        Arg,
        fixed_dictionaries({
            "name":
            _TEXT_STRATEGY,
            "type":
            dbus_signatures(**(
                {} if dbus_signature_args is None else dbus_signature_args)),
        }),
        frozensets(annotation_strategy(),
                   min_size=min_children,
                   max_size=max_children),
    )
        def _handleVariant():
            """
            Generate the correct strategy for a variant signature.

            :returns: strategy that generates an object that inhabits a variant
            :rtype: strategy
            """
            signature_strategy = dbus_signatures(max_codes=5,
                                                 min_complete_types=1,
                                                 max_complete_types=1,
                                                 blacklist="h")
            return signature_strategy.flatmap(
                lambda x: strategies.tuples(strategies.just(x),
                                            self.COMPLETE.parseString(x)[0]))
Example #5
0
class ParseTestCase(unittest.TestCase):
    """
    Test parsing various signatures.
    """

    _PARSER = Parser()

    @given(dbus_signatures())
    @settings(max_examples=50, deadline=None)
    def test_parsing(self, signature):
        """
        Test that parsing is always succesful on valid strings.
        """
        self.assertIsNotNone(
            self._PARSER.PARSER.parseString(signature, parseAll=True))
Example #6
0
class ParseTestCase(unittest.TestCase):
    """
    Test parsing various signatures.
    """

    _PARSER = Parser()

    @given(dbus_signatures())
    @settings(max_examples=100)
    def testParsing(self, signature):
        """
        Test that parsing is always succesful on valid strings.
        """
        self.assertIsNotNone(
            self._PARSER.PARSER.parseString(signature, parseAll=True))

    def testExceptions(self):
        """
        Test failure on some invalid strings.
        """
        parser = self._PARSER.PARSER
        with self.assertRaises(pyparsing.ParseException):
            parser.parseString('a', parseAll=True)
        with self.assertRaises(pyparsing.ParseException):
            parser.parseString('()', parseAll=True)
        with self.assertRaises(pyparsing.ParseException):
            parser.parseString('{}', parseAll=True)
        with self.assertRaises(pyparsing.ParseException):
            parser.parseString('{b}', parseAll=True)
        with self.assertRaises(pyparsing.ParseException):
            parser.parseString('a{b}', parseAll=True)
        with self.assertRaises(pyparsing.ParseException):
            parser.parseString('a{}', parseAll=True)
        with self.assertRaises(pyparsing.ParseException):
            parser.parseString('a{byy}', parseAll=True)
        with self.assertRaises(pyparsing.ParseException):
            parser.parseString('a{ayy}', parseAll=True)
class SignatureStrategyTestCase(unittest.TestCase):
    """
    Test for the signature strategy.
    """

    @given(
        strategies.lists(
            strategies.sampled_from(_CODES),
            min_size=1,
            max_size=len(_CODES) - 1,
            unique=True,
        ).flatmap(
            lambda x: strategies.tuples(
                strategies.just(x), dbus_signatures(blacklist=x)
            )
        )
    )
    @settings(max_examples=50, suppress_health_check=[HealthCheck.too_slow])
    def test_omits_blacklist(self, strategy):
        """
        Make sure all characters in blacklist are missing from signature.
        """
        (blacklist, signature) = strategy
        self.assertEqual([x for x in blacklist if x in signature], [])

    @given(
        strategies.integers(min_value=2, max_value=10).flatmap(
            lambda x: strategies.tuples(
                strategies.just(x),
                dbus_signatures(
                    max_codes=x,
                    min_complete_types=1,
                    max_complete_types=1,
                    exclude_dicts=True,
                ),
            )
        )
    )
    @settings(max_examples=50, suppress_health_check=[HealthCheck.too_slow])
    def test_bounds(self, strategy):
        """
        Verify that the number of codes in a single complete type does not
        exceed the max number of codes, so long as dict entry types are omitted.
        """
        (max_codes, signature) = strategy
        leaves = [x for x in signature if x in _CODES]
        self.assertLessEqual(len(leaves), max_codes)

    @given(strategies.data())  # pylint: disable=no-value-for-parameter
    @settings(max_examples=50, suppress_health_check=[HealthCheck.too_slow])
    # pylint: disable=no-self-use
    def test_no_blacklist(self, data):
        """
        Just make sure there is a result for an arbitrary legal strategy.
        """
        # pylint: disable=no-value-for-parameter
        data.draw(data.draw(dbus_signature_strategy()))

    def test_superset_blacklist(self):
        """
        Verify correct behavior when blacklist contains all type codes.
        """
        blacklist = "".join(_CODES)
        with self.assertRaises(errors.InvalidArgument):
            dbus_signatures(blacklist=blacklist)

    def test_conflicting_min_max(self):
        """
        If the minimum complete types is greater than the maximum, must fail.
        """
        with self.assertRaises(errors.InvalidArgument):
            dbus_signatures(min_complete_types=3, max_complete_types=2)

    def test_negative_max(self):
        """
        If the max is less than 0, must fail.
        """
        with self.assertRaises(errors.InvalidArgument):
            dbus_signatures(min_complete_types=-1)

    def test_non_positive_max(self):
        """
        If the maximum struct length is less than 1, must fail.
        """
        with self.assertRaises(errors.InvalidArgument):
            dbus_signatures(min_struct_len=0)

    def test_conflicting_min_max_struct_len(self):
        """
        If the minimum complete types is greater than the maximum, must fail.
        """
        with self.assertRaises(errors.InvalidArgument):
            dbus_signatures(min_struct_len=3, max_struct_len=2)

    def test_max_type_codes(self):
        """
        If the maximum type codes is less than 1, must fail.
        """
        with self.assertRaises(errors.InvalidArgument):
            dbus_signatures(max_codes=0)
 def test_max_type_codes(self):
     """
     If the maximum type codes is less than 1, must fail.
     """
     with self.assertRaises(errors.InvalidArgument):
         dbus_signatures(max_codes=0)
 def test_conflicting_min_max_struct_len(self):
     """
     If the minimum complete types is greater than the maximum, must fail.
     """
     with self.assertRaises(errors.InvalidArgument):
         dbus_signatures(min_struct_len=3, max_struct_len=2)
 def test_non_positive_max(self):
     """
     If the maximum struct length is less than 1, must fail.
     """
     with self.assertRaises(errors.InvalidArgument):
         dbus_signatures(min_struct_len=0)
 def test_negative_max(self):
     """
     If the max is less than 0, must fail.
     """
     with self.assertRaises(errors.InvalidArgument):
         dbus_signatures(min_complete_types=-1)
Example #12
0
class ParseTestCase(unittest.TestCase):
    """
    Test parsing various signatures.
    """

    @given(
        dbus_signatures(
            min_complete_types=1, max_complete_types=1, blacklist="h"
        ).flatmap(
            lambda s: strategies.tuples(
                strategies.just(s), STRATEGY_GENERATOR.parseString(s, parseAll=True)[0]
            )
        )
    )
    @settings(deadline=None, suppress_health_check=[HealthCheck.too_slow])
    def test_parsing(self, strat):
        """
        Test that parsing is always succesful.

        Verify that the original signature corresponds to the signature
        returned by the parser and to the signature of the generated value.

        Verify that the variant levels always descend within the constructed
        value.
        """
        (a_signature, base_type_object) = strat

        (func, sig_synth) = xformers(a_signature)[0]
        value = func(base_type_object)
        sig_orig = dbus.Signature(a_signature)

        self.assertEqual(sig_orig, sig_synth)

        self.assertEqual(signature(value), sig_orig)

    @given(
        dbus_signatures(min_complete_types=1, blacklist="h")
        .map(lambda s: f"({s})")
        .flatmap(
            lambda s: strategies.tuples(
                strategies.just(s), STRATEGY_GENERATOR.parseString(s, parseAll=True)[0]
            )
        )
    )
    @settings(
        max_examples=10, suppress_health_check=[HealthCheck.too_slow], deadline=None
    )
    def test_struct(self, strat):
        """
        Test exception throwing on a struct signature when number of items
        is not equal to number of complete types in struct signature.
        """
        (sig, struct) = strat

        xform = xformer(sig)

        with self.assertRaises(IntoDPUnexpectedValueError):
            xform([struct + (1,)])

        with self.assertRaises(IntoDPUnexpectedValueError):
            xform([struct[:-1]])

    @given(dbus_signatures(blacklist="hbs", exclude_dicts=True))
    @settings(max_examples=100)
    @example(sig="v")
    def test_exceptions(self, sig):
        """
        Test that an exception is raised for a dict if '{' is blacklisted.

        Need to also blacklist 'b' and 's', since dbus.String and dbus.Boolean
        constructors can both convert a dict.
        """

        xform = xformer(sig)

        with self.assertRaises(IntoDPUnexpectedValueError):
            xform([{True: True}])
Example #13
0
# isort: FIRSTPARTY
from dbus_signature_pyparsing import Parser
from hs_dbus_signature import dbus_signatures

# isort: LOCAL
from into_dbus_python import signature, xformer, xformers
from into_dbus_python._errors import IntoDPUnexpectedValueError

settings.register_profile(
    "tracing", deadline=None, suppress_health_check=[HealthCheck.too_slow]
)
if sys.gettrace() is not None:
    settings.load_profile("tracing")

# Omits h, unix fd, because it is unclear what are valid fds for dbus
SIGNATURE_STRATEGY = dbus_signatures(max_codes=20, blacklist="h")

OBJECT_PATH_STRATEGY = strategies.builds(
    "/".__add__,
    strategies.builds(
        "/".join,
        strategies.lists(
            strategies.text(
                alphabet=list(
                    string.digits
                    + string.ascii_uppercase
                    + string.ascii_lowercase
                    + "_"
                ),
                min_size=1,
                max_size=10,
Example #14
0
class ParseTestCase(unittest.TestCase):
    """
    Test parsing various signatures.
    """
    @given(
        dbus_signatures(
            min_complete_types=1, max_complete_types=1,
            blacklist="h").flatmap(lambda s: strategies.tuples(
                strategies.just(s),
                STRATEGY_GENERATOR.parseString(s, parseAll=True)[0])))
    @settings(deadline=None, suppress_health_check=[HealthCheck.too_slow])
    def test_parsing(self, strat):
        """
        Test that parsing is always succesful.

        Verify that the original signature corresponds to the signature
        returned by the parser and to the signature of the generated value.

        Verify that the variant levels always descend within the constructed
        value.
        """
        (a_signature, base_type_object) = strat

        (func, sig_synth) = xformers(a_signature)[0]
        (value, level) = func(base_type_object)
        sig_orig = dbus.Signature(a_signature)

        self.assertEqual(sig_orig, sig_synth)

        if 'v' not in sig_orig:
            self.assertEqual(level, 0)
        self.assertIsNotNone(_descending(value))
        self.assertEqual(signature(value), sig_orig)

    @given(
        dbus_signatures(min_complete_types=1, blacklist="h").map(
            lambda s: "(%s)" % s).flatmap(lambda s: strategies.tuples(
                strategies.just(s),
                STRATEGY_GENERATOR.parseString(s, parseAll=True)[0])))
    @settings(max_examples=10,
              suppress_health_check=[HealthCheck.too_slow],
              deadline=None)
    def test_struct(self, strat):
        """
        Test exception throwing on a struct signature when number of items
        is not equal to number of complete types in struct signature.
        """
        (sig, struct) = strat

        xform = xformer(sig)

        with self.assertRaises(IntoDPError):
            xform([struct + (1, )])

        with self.assertRaises(IntoDPError):
            xform([struct[:-1]])

    @given(dbus_signatures(blacklist="hbs", exclude_dicts=True))
    @settings(max_examples=100)
    def test_exceptions(self, sig):
        """
        Test that an exception is raised for a dict if '{' is blacklisted.

        Need to also blacklist 'b' and 's', since dbus.String and dbus.Boolean
        constructors can both convert a dict.
        """

        xform = xformer(sig)

        with self.assertRaises(IntoDPError):
            xform([{True: True}])

    def test_bad_array_value(self):
        """
        Verify that passing a dict for an array will raise an exception.
        """
        with self.assertRaises(IntoDPError):
            xformer('a(qq)')([dict()])

    def test_variant_depth(self):
        """
        Verify that a nested variant has appropriate variant depth.
        """
        self.assertEqual(
            xformer('v')([('v', ('v', ('b', False)))])[0].variant_level, 3)
        self.assertEqual(
            xformer('v')([('v', ('ab', [False]))])[0],
            dbus.Array([dbus.Boolean(False)], signature='b', variant_level=2))
        self.assertEqual(
            xformer('av')([([('v', ('b', False))])])[0],
            dbus.Array([dbus.Boolean(False, variant_level=2)], signature="v"))

    @given(STRATEGY_GENERATOR.parseString('v', parseAll=True)[0])
    @settings(max_examples=50)
    def test_unpacking(self, value):
        """
        Test that signature unpacking works.
        """
        dbus_value = xformer('v')([value])[0]
        unpacked = signature(dbus_value, unpack=True)
        packed = signature(dbus_value)

        self.assertEqual(packed, 'v')
        self.assertFalse(unpacked.startswith('v'))
Example #15
0
class SignatureStrategyHypothesisTestCase(unittest.TestCase):
    """
    Test for the signature strategy.
    """
    @given(
        strategies.lists(
            strategies.sampled_from(_CODES),
            min_size=1,
            max_size=len(_CODES) - 1,
            unique=True,
        ).flatmap(lambda x: strategies.tuples(strategies.just(x),
                                              dbus_signatures(blacklist=x))))
    @settings(max_examples=50, suppress_health_check=[HealthCheck.too_slow])
    def test_omits_blacklist(self, strategy):
        """
        Make sure all characters in blacklist are missing from signature.
        """
        (blacklist, signature) = strategy
        self.assertEqual([x for x in blacklist if x in signature], [])

    @given(
        strategies.just([x for x in _CODES
                         if x != "v"]).flatmap(lambda x: strategies.tuples(
                             strategies.just(x), dbus_signatures(blacklist=x)))
    )
    @settings(max_examples=5, suppress_health_check=[HealthCheck.too_slow])
    def test_blacklist_all_but_v(self, strategy):
        """
        Test correct behavior when blacklist excludes all codes but 'v'.
        """
        (blacklist, signature) = strategy
        self.assertEqual([x for x in blacklist if x in signature], [])

    @given(
        strategies.integers(min_value=2,
                            max_value=10).flatmap(lambda x: strategies.tuples(
                                strategies.just(x),
                                dbus_signatures(
                                    max_codes=x,
                                    min_complete_types=1,
                                    max_complete_types=1,
                                    exclude_dicts=True,
                                ),
                            )))
    @settings(max_examples=50, suppress_health_check=[HealthCheck.too_slow])
    def test_bounds(self, strategy):
        """
        Verify that the number of codes in a single complete type does not
        exceed the max number of codes, so long as dict entry types are omitted.
        """
        (max_codes, signature) = strategy
        leaves = [x for x in signature if x in _CODES]
        self.assertLessEqual(len(leaves), max_codes)

    @given(strategies.data())  # pylint: disable=no-value-for-parameter
    @settings(max_examples=50, suppress_health_check=[HealthCheck.too_slow])
    # pylint: disable=no-self-use
    def test_no_blacklist(self, data):
        """
        Just make sure there is a result for an arbitrary legal strategy.
        """
        # pylint: disable=no-value-for-parameter
        data.draw(data.draw(dbus_signature_strategy()))