[pypy-commit] pypy default: Test with hypothesis, fix for a corner case of startswith()

arigo pypy.commits at gmail.com
Sat Oct 14 05:43:34 EDT 2017


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r92754:88bed3bb8ad4
Date: 2017-10-14 11:16 +0200
http://bitbucket.org/pypy/pypy/changeset/88bed3bb8ad4/

Log:	Test with hypothesis, fix for a corner case of startswith()

diff --git a/pypy/objspace/std/stringmethods.py b/pypy/objspace/std/stringmethods.py
--- a/pypy/objspace/std/stringmethods.py
+++ b/pypy/objspace/std/stringmethods.py
@@ -633,13 +633,16 @@
 
     def _startswith(self, space, value, w_prefix, start, end):
         prefix = self._op_val(space, w_prefix)
-        if start > len(value):
-            return self._starts_ends_overflow(prefix)
+        if self._starts_ends_unicode:   # bug-to-bug compat
+            if len(prefix) == 0:
+                return True
+        else:
+            if start > len(value):
+                return False
         return startswith(value, prefix, start, end)
 
-    def _starts_ends_overflow(self, prefix):
-        return False     # bug-to-bug compat: this is for strings and
-                         # bytearrays, but overridden for unicodes
+    _starts_ends_unicode = False  # bug-to-bug compat: this is for strings and
+                                  # bytearrays, but overridden for unicodes
 
     def descr_endswith(self, space, w_suffix, w_start=None, w_end=None):
         value, start, end, _ = self._convert_idx_params(space, w_start, w_end)
@@ -656,8 +659,12 @@
 
     def _endswith(self, space, value, w_prefix, start, end):
         prefix = self._op_val(space, w_prefix)
-        if start > len(value):
-            return self._starts_ends_overflow(prefix)
+        if self._starts_ends_unicode:   # bug-to-bug compat
+            if len(prefix) == 0:
+                return True
+        else:
+            if start > len(value):
+                return False
         return endswith(value, prefix, start, end)
 
     def _strip(self, space, w_chars, left, right, name='strip'):
diff --git a/pypy/objspace/std/test/test_bytesobject.py b/pypy/objspace/std/test/test_bytesobject.py
--- a/pypy/objspace/std/test/test_bytesobject.py
+++ b/pypy/objspace/std/test/test_bytesobject.py
@@ -1,3 +1,7 @@
+from hypothesis import given, strategies, settings, example
+from pypy.interpreter.error import OperationError
+
+
 class TestW_BytesObject:
 
     def teardown_method(self, method):
@@ -86,6 +90,72 @@
         w_bytes = self.space.newbytes('abcd')
         assert self.space.listview_bytes(w_bytes) == list("abcd")
 
+    @given(strategies.binary(), strategies.integers(min_value=0, max_value=10),
+                                strategies.integers(min_value=-1, max_value=10))
+    def test_hypo_index_find(self, u, start, len1):
+        if start + len1 < 0:
+            return   # skip this case
+        v = u[start : start + len1]
+        space = self.space
+        w_u = space.wrap(u)
+        w_v = space.wrap(v)
+        expected = u.find(v, start, start + len1)
+        try:
+            w_index = space.call_method(w_u, 'index', w_v,
+                                        space.newint(start),
+                                        space.newint(start + len1))
+        except OperationError as e:
+            if not e.match(space, space.w_ValueError):
+                raise
+            assert expected == -1
+        else:
+            assert space.int_w(w_index) == expected >= 0
+
+        w_index = space.call_method(w_u, 'find', w_v,
+                                    space.newint(start),
+                                    space.newint(start + len1))
+        assert space.int_w(w_index) == expected
+
+        rexpected = u.rfind(v, start, start + len1)
+        try:
+            w_index = space.call_method(w_u, 'rindex', w_v,
+                                        space.newint(start),
+                                        space.newint(start + len1))
+        except OperationError as e:
+            if not e.match(space, space.w_ValueError):
+                raise
+            assert rexpected == -1
+        else:
+            assert space.int_w(w_index) == rexpected >= 0
+
+        w_index = space.call_method(w_u, 'rfind', w_v,
+                                    space.newint(start),
+                                    space.newint(start + len1))
+        assert space.int_w(w_index) == rexpected
+
+        expected = u.startswith(v, start)
+        w_res = space.call_method(w_u, 'startswith', w_v,
+                                  space.newint(start))
+        assert w_res is space.newbool(expected)
+
+        expected = u.startswith(v, start, start + len1)
+        w_res = space.call_method(w_u, 'startswith', w_v,
+                                  space.newint(start),
+                                  space.newint(start + len1))
+        assert w_res is space.newbool(expected)
+
+        expected = u.endswith(v, start)
+        w_res = space.call_method(w_u, 'endswith', w_v,
+                                  space.newint(start))
+        assert w_res is space.newbool(expected)
+
+        expected = u.endswith(v, start, start + len1)
+        w_res = space.call_method(w_u, 'endswith', w_v,
+                                  space.newint(start),
+                                  space.newint(start + len1))
+        assert w_res is space.newbool(expected)
+
+
 class AppTestBytesObject:
 
     def test_format_wrongchar(self):
diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py
--- a/pypy/objspace/std/test/test_unicodeobject.py
+++ b/pypy/objspace/std/test/test_unicodeobject.py
@@ -1,5 +1,7 @@
 import py
 import sys
+from hypothesis import given, strategies, settings, example
+from pypy.interpreter.error import OperationError
 
 
 class TestUnicodeObject:
@@ -32,6 +34,71 @@
                 space.w_unicode, "__new__", space.w_unicode, w_uni)
         assert w_new is w_uni
 
+    @given(strategies.text(), strategies.integers(min_value=0, max_value=10),
+                              strategies.integers(min_value=-1, max_value=10))
+    def test_hypo_index_find(self, u, start, len1):
+        if start + len1 < 0:
+            return   # skip this case
+        v = u[start : start + len1]
+        space = self.space
+        w_u = space.wrap(u)
+        w_v = space.wrap(v)
+        expected = u.find(v, start, start + len1)
+        try:
+            w_index = space.call_method(w_u, 'index', w_v,
+                                        space.newint(start),
+                                        space.newint(start + len1))
+        except OperationError as e:
+            if not e.match(space, space.w_ValueError):
+                raise
+            assert expected == -1
+        else:
+            assert space.int_w(w_index) == expected >= 0
+
+        w_index = space.call_method(w_u, 'find', w_v,
+                                    space.newint(start),
+                                    space.newint(start + len1))
+        assert space.int_w(w_index) == expected
+
+        rexpected = u.rfind(v, start, start + len1)
+        try:
+            w_index = space.call_method(w_u, 'rindex', w_v,
+                                        space.newint(start),
+                                        space.newint(start + len1))
+        except OperationError as e:
+            if not e.match(space, space.w_ValueError):
+                raise
+            assert rexpected == -1
+        else:
+            assert space.int_w(w_index) == rexpected >= 0
+
+        w_index = space.call_method(w_u, 'rfind', w_v,
+                                    space.newint(start),
+                                    space.newint(start + len1))
+        assert space.int_w(w_index) == rexpected
+
+        expected = u.startswith(v, start)
+        w_res = space.call_method(w_u, 'startswith', w_v,
+                                  space.newint(start))
+        assert w_res is space.newbool(expected)
+
+        expected = u.startswith(v, start, start + len1)
+        w_res = space.call_method(w_u, 'startswith', w_v,
+                                  space.newint(start),
+                                  space.newint(start + len1))
+        assert w_res is space.newbool(expected)
+
+        expected = u.endswith(v, start)
+        w_res = space.call_method(w_u, 'endswith', w_v,
+                                  space.newint(start))
+        assert w_res is space.newbool(expected)
+
+        expected = u.endswith(v, start, start + len1)
+        w_res = space.call_method(w_u, 'endswith', w_v,
+                                  space.newint(start),
+                                  space.newint(start + len1))
+        assert w_res is space.newbool(expected)
+
 
 class AppTestUnicodeStringStdOnly:
     def test_compares(self):
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -419,8 +419,7 @@
                 cased = True
         return space.newbool(cased)
 
-    def _starts_ends_overflow(self, prefix):
-        return len(prefix) == 0
+    _starts_ends_unicode = True
 
 
 def wrapunicode(space, uni):


More information about the pypy-commit mailing list