#!/usr/bin/env python
"""Tests that don't need an active D-Bus connection to run, but can be
run in isolation.
"""
# Copyright (C) 2006 Collabora Ltd. <http://www.collabora.co.uk/>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use, copy,
# modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
# DEALINGS IN THE SOFTWARE.
from __future__ import unicode_literals
import sys
import os
import unittest
builddir = os.path.normpath(os.environ["DBUS_TOP_BUILDDIR"])
pydir = os.path.normpath(os.environ["DBUS_TOP_SRCDIR"])
import _dbus_bindings
import dbus
import dbus.lowlevel as lowlevel
import dbus.types as types
from dbus._compat import is_py2, is_py3
if is_py3:
    def make_long(n):
        return n
else:
    def make_long(n):
        return long(n)
# Check that we're using the right versions
if not dbus.__file__.startswith(pydir):
    raise Exception("DBus modules (%s) are not being picked up from the package"%dbus.__file__)
if not _dbus_bindings.__file__.startswith(builddir):
    raise Exception("DBus modules (%s) are not being picked up from the package"%_dbus_bindings.__file__)
assert (_dbus_bindings._python_version & 0xffff0000
        == sys.hexversion & 0xffff0000), \
        '_dbus_bindings was compiled for Python %x but this is Python %x, '\
        'a different major version'\
        % (_dbus_bindings._python_version, sys.hexversion)
assert _dbus_bindings.__version__ == os.environ['DBUS_PYTHON_VERSION'], \
        '_dbus_bindings was compiled as version %s but Automake says '\
        'we should be version %s' \
        % (_dbus_bindings.__version__, os.environ['DBUS_PYTHON_VERSION'])
class TestTypes(unittest.TestCase):
    def test_Dictionary(self):
        self.assertEqual(types.Dictionary({'foo':'bar'}), {'foo':'bar'})
        self.assertEqual(types.Dictionary({}, variant_level=2), {})
        self.assertEqual(types.Dictionary({}, variant_level=2).variant_level, 2)
    def test_Array(self):
        self.assertEqual(types.Array(['foo','bar']), ['foo','bar'])
        self.assertEqual(types.Array([], variant_level=2), [])
        self.assertEqual(types.Array([], variant_level=2).variant_level, 2)
    def test_Double(self):
        self.assertEqual(types.Double(0.0), 0.0)
        self.assertEqual(types.Double(0.125, variant_level=2), 0.125)
        self.assertEqual(types.Double(0.125, variant_level=2).variant_level, 2)
    def test_Struct(self):
        x = types.Struct(('',))
        self.assertEqual(x.variant_level, 0)
        self.assertEqual(x, ('',))
        x = types.Struct('abc', variant_level=42)
        self.assertEqual(x.variant_level, 42)
        self.assertEqual(x, ('a','b','c'))
    def test_Byte(self):
        self.assertEqual(types.Byte(b'x', variant_level=2),
                          types.Byte(ord('x')))
        self.assertEqual(types.Byte(1), 1)
        self.assertEqual(types.Byte(make_long(1)), 1)
        self.assertRaises(Exception, lambda: types.Byte(b'ab'))
        self.assertRaises(TypeError, types.Byte, '\x12xxxxxxxxxxxxx')
        # Byte from a unicode object: what would that even mean?
        self.assertRaises(Exception,
                lambda: types.Byte(b'a'.decode('latin-1')))
    def test_ByteArray(self):
        self.assertEqual(types.ByteArray(b''), b'')
    def test_object_path_attr(self):
        class MyObject(object):
            __dbus_object_path__ = '/foo'
        from _dbus_bindings import SignalMessage
        self.assertEqual(SignalMessage.guess_signature(MyObject()), 'o')
    def test_integers(self):
        subclasses = [int]
        if is_py2:
            subclasses.append(long)
        subclasses = tuple(subclasses)
        # This is an API guarantee. Note that exactly which of these types
        # are ints and which of them are longs is *not* guaranteed.
        for cls in (types.Int16, types.UInt16, types.Int32, types.UInt32,
            types.Int64, types.UInt64):
            self.assertTrue(issubclass(cls, subclasses))
            self.assertTrue(isinstance(cls(0), subclasses))
            self.assertEqual(cls(0), 0)
            self.assertEqual(cls(23, variant_level=1), 23)
            self.assertEqual(cls(23, variant_level=1).variant_level, 1)
    def test_integer_limits_16(self):
        self.assertEqual(types.Int16(0x7fff), 0x7fff)
        self.assertEqual(types.Int16(-0x8000), -0x8000)
        self.assertEqual(types.UInt16(0xffff), 0xffff)
        self.assertRaises(Exception, types.Int16, 0x8000)
        self.assertRaises(Exception, types.Int16, -0x8001)
        self.assertRaises(Exception, types.UInt16, 0x10000)
    def test_integer_limits_32(self):
        self.assertEqual(types.Int32(0x7fffffff), 0x7fffffff)
        self.assertEqual(types.Int32(make_long(-0x80000000)), 
                         make_long(-0x80000000))
        self.assertEqual(types.UInt32(make_long(0xffffffff)), 
                         make_long(0xffffffff))
        self.assertRaises(Exception, types.Int32, make_long(0x80000000))
        self.assertRaises(Exception, types.Int32, make_long(-0x80000001))
        self.assertRaises(Exception, types.UInt32, make_long(0x100000000))
    def test_integer_limits_64(self):
        self.assertEqual(types.Int64(make_long(0x7fffffffffffffff)), 
                         make_long(0x7fffffffffffffff))
        self.assertEqual(types.Int64(make_long(-0x8000000000000000)), 
                         make_long(-0x8000000000000000))
        self.assertEqual(types.UInt64(make_long(0xffffffffffffffff)), 
                         make_long(0xffffffffffffffff))
        self.assertRaises(Exception, types.Int16, 
                          make_long(0x8000000000000000))
        self.assertRaises(Exception, types.Int16, 
                          make_long(-0x8000000000000001))
        self.assertRaises(Exception, types.UInt16, 
                          make_long(0x10000000000000000))
    def test_Signature(self):
        self.assertRaises(Exception, types.Signature, 'a')
        self.assertEqual(types.Signature('ab', variant_level=23), 'ab')
        self.assertTrue(isinstance(types.Signature('ab'), str))
        self.assertEqual(tuple(types.Signature('ab(xt)a{sv}')),
                         ('ab', '(xt)', 'a{sv}'))
        self.assertTrue(isinstance(tuple(types.Signature('ab'))[0],
                                   types.Signature))
class TestMessageMarshalling(unittest.TestCase):
    def test_path(self):
        s = lowlevel.SignalMessage('/a/b/c', 'foo.bar', 'baz')
        self.assertEqual(s.get_path(), types.ObjectPath('/a/b/c'))
        self.assertEqual(type(s.get_path()), types.ObjectPath)
        self.assertEqual(s.get_path_decomposed(), ['a', 'b', 'c'])
        # this is true in both major versions: it's a bytestring in
        # Python 2 and a Unicode string in Python 3
        self.assertEqual(type(s.get_path_decomposed()[0]), str)
        self.assertTrue(s.has_path('/a/b/c'))
        self.assertFalse(s.has_path('/a/b'))
        self.assertFalse(s.has_path('/a/b/c/d'))
        s = lowlevel.SignalMessage('/', 'foo.bar', 'baz')
        self.assertEqual(s.get_path(), types.ObjectPath('/'))
        self.assertEqual(s.get_path().__class__, types.ObjectPath)
        self.assertEqual(s.get_path_decomposed(), [])
        self.assertTrue(s.has_path('/'))
        self.assertFalse(s.has_path(None))
    def test_sender(self):
        s = lowlevel.SignalMessage('/a/b/c', 'foo.bar', 'baz')
        self.assertEqual(s.get_sender(), None)
        self.assertFalse(s.has_sender(':1.23'))
        s.set_sender(':1.23')
        self.assertEqual(s.get_sender(), ':1.23')
        # bytestring in Python 2, Unicode string in Python 3
        self.assertEqual(type(s.get_sender()), str)
        self.assertTrue(s.has_sender(':1.23'))
    def test_destination(self):
        s = lowlevel.SignalMessage('/a/b/c', 'foo.bar', 'baz')
        self.assertEqual(s.get_destination(), None)
        self.assertFalse(s.has_destination(':1.23'))
        s.set_destination(':1.23')
        self.assertEqual(s.get_destination(), ':1.23')
        # bytestring in Python 2, Unicode string in Python 3
        self.assertEqual(type(s.get_destination()), str)
        self.assertTrue(s.has_destination(':1.23'))
    def test_interface(self):


Answer:         s = lowlevel.SignalMessage('/a/b/c', 'foo.bar', 'baz')