Repository: HypothesisWorks/hypothesis

Issue:
from_type(xrange) is broken
The following test demonstrates this bug:

```python
@settings(max_examples=1000)
@given(type_=st.from_type(xrange))
def test_from_type_xrange(type_):
    pass
```

>OverflowError: Python int too large to convert to C long


Discussion:
I think our test suite is missing the following test, which should be added to `tests/cover/test_type_lookup.py`:

```python
from hypothesis.searchstrategy.types import _global_type_lookup

@pytest.mark.parametrize("typ", sorted(_global_type_lookup, key=str))
@given(data())
def test_can_generate_from_all_registered_types(data, typ):
    ex = data.draw(from_type(typ))
    assert isinstance(ex, typ)
```
Everything looks fine for Python 2 once I make the `xrange` fix. 

It looks like there are a few complications even on the Python 3 end of things because of the items from the `typing` module. Calling `isinstance` with some of these doesn't work. How do you want to proceed with these items:
- Each of the `SupportsXXXX` objects we get: `TypeError: Protocols cannot be used with isinstance().`
- `BytesIO` & `StringIO` values are not instances of their `typing` counterparts.
- The draw for `typing.Type` fails with: `where False = isinstance(+CT_co, typing.Type)`

I can make a mapping back to the appropriate types that gets used within the test for the first two points, and that should take care of those easily enough. I am not sure what to make of  the ` typing.Type` case.


I'd just exclude anything where the `__module__` attribute is "typing"; as the runtime issues are more trouble than they're worth and well tested in the py3 tests. 
That's a relief. *Much* simpler.

Resolving patch:
diff --git a/hypothesis-python/src/hypothesis/searchstrategy/types.py b/hypothesis-python/src/hypothesis/searchstrategy/types.py
--- a/hypothesis-python/src/hypothesis/searchstrategy/types.py
+++ b/hypothesis-python/src/hypothesis/searchstrategy/types.py
@@ -25,6 +25,7 @@
 import inspect
 import io
 import numbers
+import sys
 import uuid
 
 import hypothesis.strategies as st
@@ -198,14 +199,16 @@ def from_typing_type(thing):
 }
 
 if PY2:
+    # xrange's |stop - start| must fit in a C long
+    int64_strat = st.integers(-sys.maxint // 2, sys.maxint // 2)  # noqa
     _global_type_lookup.update(
         {
             int: st.integers().filter(lambda x: isinstance(x, int)),
             long: st.integers().map(long),  # noqa
-            xrange: st.integers(min_value=0).map(xrange)  # noqa
-            | st.builds(xrange, st.integers(), st.integers())  # noqa
+            xrange: st.integers(min_value=0, max_value=sys.maxint).map(xrange)  # noqa
+            | st.builds(xrange, int64_strat, int64_strat)  # noqa
             | st.builds(
-                xrange, st.integers(), st.integers(), st.integers().filter(bool)  # noqa
+                xrange, int64_strat, int64_strat, int64_strat.filter(bool)  # noqa
             ),
         }
     )


Test patch:
diff --git a/hypothesis-python/tests/cover/test_float_utils.py b/hypothesis-python/tests/cover/test_float_utils.py
--- a/hypothesis-python/tests/cover/test_float_utils.py
+++ b/hypothesis-python/tests/cover/test_float_utils.py
@@ -17,8 +17,30 @@
 
 from __future__ import absolute_import, division, print_function
 
-from hypothesis.internal.floats import count_between_floats
+import math
+
+import pytest
+
+from hypothesis.internal.floats import count_between_floats, next_down, next_up
 
 
 def test_can_handle_straddling_zero():
     assert count_between_floats(-0.0, 0.0) == 2
+
+
+@pytest.mark.parametrize(
+    "func,val",
+    [
+        (next_up, float("nan")),
+        (next_up, float("inf")),
+        (next_up, -0.0),
+        (next_down, float("nan")),
+        (next_down, float("-inf")),
+        (next_down, 0.0),
+    ],
+)
+def test_next_float_equal(func, val):
+    if math.isnan(val):
+        assert math.isnan(func(val))
+    else:
+        assert func(val) == val
diff --git a/hypothesis-python/tests/cover/test_type_lookup.py b/hypothesis-python/tests/cover/test_type_lookup.py
--- a/hypothesis-python/tests/cover/test_type_lookup.py
+++ b/hypothesis-python/tests/cover/test_type_lookup.py
@@ -31,6 +31,7 @@
 )
 from hypothesis.internal.compat import PY2, integer_types
 from hypothesis.searchstrategy import types
+from hypothesis.searchstrategy.types import _global_type_lookup
 from tests.common.utils import checks_deprecated_behaviour
 
 # Build a set of all types output by core strategies
@@ -218,3 +219,12 @@ def test_uninspectable_builds():
 def test_uninspectable_from_type():
     with pytest.raises(TypeError, match="object is not callable"):
         st.from_type(BrokenClass).example()
+
+
+@pytest.mark.parametrize(
+    "typ", sorted([x for x in _global_type_lookup if x.__module__ != "typing"], key=str)
+)
+@given(data=st.data())
+def test_can_generate_from_all_registered_types(data, typ):
+    value = data.draw(st.from_type(typ), label="value")
+    assert isinstance(value, typ)