def test_nsstring_index_rindex(self): """The index and rindex methods work on NSString.""" py_haystack = type(self).HAYSTACK ns_haystack = ns_from_py(py_haystack) for py_needle in type(self).NEEDLES: for start, end in type(self).RANGES: with self.subTest(py_needle=py_needle, start=start, end=end): ns_needle = ns_from_py(py_needle) try: index = py_haystack.index(py_needle, start, end) except ValueError: with self.assertRaises(ValueError): ns_haystack.index(ns_needle, start, end) else: self.assertEqual(ns_haystack.index(ns_needle, start, end), index) try: rindex = py_haystack.rindex(py_needle, start, end) except ValueError: with self.assertRaises(ValueError): ns_haystack.rindex(ns_needle, start, end) else: self.assertEqual(ns_haystack.rindex(ns_needle, start, end), rindex)
def test_nsstring_eq_nsstring(self): """Two NSStrings can be checked for equality.""" first = ns_from_py('first') second = ns_from_py('second') self.assertEqual(first, first) self.assertNotEqual(first, second) self.assertEqual(second, second)
def test_nsstring_mul_rmul(self): """The * operator works on NSString.""" for py_str in type(self).TEST_STRINGS: for n in (-5, 0, 1, 2, 5): with self.subTest(py_str=py_str, n=n): ns_str = ns_from_py(py_str) py_repeated = py_str * n ns_repeated = ns_from_py(py_repeated) self.assertEqual(ns_str * n, ns_repeated) self.assertEqual(n * ns_str, ns_repeated)
def test_nsstring_in(self): """The in operator works on NSString.""" py_haystack = type(self).HAYSTACK ns_haystack = ns_from_py(py_haystack) for py_needle in type(self).NEEDLES: with self.subTest(py_needle=py_needle): ns_needle = ns_from_py(py_needle) if py_needle in py_haystack: self.assertIn(ns_needle, ns_haystack) else: self.assertNotIn(ns_needle, ns_haystack)
def test_nsstring_add_radd(self): """The + operator works on NSString.""" for py_left in type(self).TEST_STRINGS: for py_right in type(self).TEST_STRINGS: with self.subTest(py_left=py_left, py_right=py_right): ns_left = ns_from_py(py_left) ns_right = ns_from_py(py_right) py_concat = py_left + py_right ns_concat = ns_from_py(py_concat) self.assertEqual(ns_left + ns_right, ns_concat) self.assertEqual(py_left + ns_right, ns_concat) self.assertEqual(ns_left + py_right, ns_concat)
def test_nsstring_compare(self): """A NSString can be compared to other strings.""" for py_left in type(self).TEST_STRINGS: for py_right in type(self).TEST_STRINGS: with self.subTest(py_left=py_left, py_right=py_right): ns_left = ns_from_py(py_left) ns_right = ns_from_py(py_right) self.assertEqual(ns_left < ns_right, py_left < py_right) self.assertEqual(ns_left <= ns_right, py_left <= py_right) self.assertEqual(ns_left >= ns_right, py_left >= py_right) self.assertEqual(ns_left > ns_right, py_left > py_right)
def test_str_eq_nsstring(self): """A Python str and a NSString can be checked for equality.""" py_first = 'first' py_second = 'second' ns_first = ns_from_py(py_first) ns_second = ns_from_py(py_second) self.assertEqual(py_first, ns_first) self.assertEqual(ns_first, py_first) self.assertNotEqual(py_first, ns_second) self.assertNotEqual(ns_first, py_second) self.assertEqual(py_second, ns_second) self.assertEqual(ns_second, py_second)
def test_nsstring_len(self): """len() works on NSString.""" for pystr in type(self).TEST_STRINGS: with self.subTest(pystr=pystr): nsstr = ns_from_py(pystr) self.assertEqual(len(nsstr), len(pystr))
def test_nsstring_as_fspath(self): """An NSString can be interpreted as a 'path-like' object""" # os.path.dirname requires a 'path-like' object. self.assertEqual( os.path.dirname(ns_from_py('/path/base/leaf')), '/path/base' )
def test_nsstring_find_rfind(self): """The find and rfind methods work on NSString.""" py_haystack = type(self).HAYSTACK ns_haystack = ns_from_py(py_haystack) for py_needle in type(self).NEEDLES: for start, end in type(self).RANGES: with self.subTest(py_needle=py_needle, start=start, end=end): ns_needle = ns_from_py(py_needle) self.assertEqual( ns_haystack.find(ns_needle, start, end), py_haystack.find(py_needle, start, end), ) self.assertEqual( ns_haystack.rfind(ns_needle, start, end), py_haystack.rfind(py_needle, start, end), )
def test_nsstring_iter(self): """A NSString can be iterated over.""" for pystr in type(self).TEST_STRINGS: with self.subTest(pystr=pystr): nsstr = ns_from_py(pystr) for nschar, pychar in zip(nsstr, pystr): self.assertEqual(nschar, pychar)
def test_nsstring_getitem_index(self): """The individual elements of a NSString can be accessed.""" for pystr in type(self).TEST_STRINGS: with self.subTest(pystr=pystr): nsstr = ns_from_py(pystr) for i, pychar in enumerate(pystr): self.assertEqual(nsstr[i], pychar)
def test_str_nsstring_conversion(self): """Python str and NSString can be converted to each other manually.""" for pystr in type(self).TEST_STRINGS: with self.subTest(pystr=pystr): nsstr = ns_from_py(pystr) self.assertIsInstance(nsstr, NSString) self.assertEqual(str(nsstr), pystr) self.assertEqual(py_from_ns(nsstr), pystr)
def test_nsstring_getitem_slice(self): """A NSString can be sliced.""" for pystr in type(self).TEST_STRINGS: for step in (None, 1, 2, -1, -2): with self.subTest(pystr=pystr, step=step): nsstr = ns_from_py(pystr) self.assertEqual(nsstr[::step], pystr[::step]) self.assertEqual(nsstr[:3:step], pystr[:3:step]) self.assertEqual(nsstr[2::step], pystr[2::step]) self.assertEqual(nsstr[1:4:step], pystr[1:4:step])
def assert_method(self, py_value, method, *args, **kwargs): ns_value = ns_from_py(py_value) try: py_method = getattr(py_value, method) except AttributeError: self.fail("Python type '{}' does not have method '{}'".format(type(py_value), method)) try: ns_method = getattr(ns_value, method) except AttributeError: self.fail("Rubicon analog for type '{}' does not have method '{}'".format(type(py_value), method)) try: py_result = py_method(*args, **kwargs) py_exception = None except Exception as e: py_exception = e py_result = None try: ns_result = ns_method(*args, **kwargs) ns_exception = None except Exception as e: ns_exception = e ns_result = None if py_exception is None and ns_exception is None: self.assertEqual( py_result, ns_result, "Different results for {}: Python = {}; ObjC = {}".format(method, py_result, ns_result) ) elif py_exception is not None: if ns_exception is not None: self.assertEqual( type(py_exception), type(ns_exception), "Different exceptions for {}: Python = {}; ObjC = {}".format(method, py_result, ns_result) ) else: self.fail("Python call for {} raised {}, but ObjC did not".format(method, type(py_exception))) else: self.fail("ObjC call for {} raised {}, but Python did not".format(method, type(py_exception)))