import io
import os
import sys
import unittest

try:
    import hypothesis
    import hypothesis.strategies as strategies
except ImportError:
    raise unittest.SkipTest('hypothesis not available')

import zstandard as zstd

from .common import (
    make_cffi,
)


s_windowlog = strategies.integers(min_value=zstd.WINDOWLOG_MIN,
                                    max_value=zstd.WINDOWLOG_MAX)
s_chainlog = strategies.integers(min_value=zstd.CHAINLOG_MIN,
                                    max_value=zstd.CHAINLOG_MAX)
s_hashlog = strategies.integers(min_value=zstd.HASHLOG_MIN,
                                max_value=zstd.HASHLOG_MAX)
s_searchlog = strategies.integers(min_value=zstd.SEARCHLOG_MIN,
                                    max_value=zstd.SEARCHLOG_MAX)
s_searchlength = strategies.integers(min_value=zstd.SEARCHLENGTH_MIN,
                                        max_value=zstd.SEARCHLENGTH_MAX)
s_targetlength = strategies.integers(min_value=zstd.TARGETLENGTH_MIN,
                                        max_value=zstd.TARGETLENGTH_MAX)
s_strategy = strategies.sampled_from((zstd.STRATEGY_FAST,
                                        zstd.STRATEGY_DFAST,
                                        zstd.STRATEGY_GREEDY,
                                        zstd.STRATEGY_LAZY,
                                        zstd.STRATEGY_LAZY2,
                                        zstd.STRATEGY_BTLAZY2,
                                        zstd.STRATEGY_BTOPT,
                                        zstd.STRATEGY_BTULTRA))


@make_cffi
@unittest.skipUnless('ZSTD_SLOW_TESTS' in os.environ, 'ZSTD_SLOW_TESTS not set')
class TestCompressionParametersHypothesis(unittest.TestCase):
    @hypothesis.given(s_windowlog, s_chainlog, s_hashlog, s_searchlog,
                        s_searchlength, s_targetlength, s_strategy)
    def test_valid_init(self, windowlog, chainlog, hashlog, searchlog,
                        searchlength, targetlength, strategy):
        # ZSTD_checkCParams moves the goal posts on us from what's advertised
        # in the constants. So move along with them.
        if searchlength == zstd.SEARCHLENGTH_MIN and strategy in (zstd.STRATEGY_FAST, zstd.STRATEGY_GREEDY):
            searchlength += 1
        elif searchlength == zstd.SEARCHLENGTH_MAX and strategy != zstd.STRATEGY_FAST:
            searchlength -= 1

        # 32-bit machines may have trouble allocating larger sizes. So cap
        # them. This reduces test coverage for this machine type. But 64-bit
        # should still have us covered.
        maxint = sys.maxint if hasattr(sys, 'maxint') else sys.maxsize
        if maxint <= 2**32:
            windowlog = min(windowlog, 25)
            hashlog = min(hashlog, 25)
            chainlog = min(chainlog, 26)
            searchlog = min(searchlog, 24)

        p = zstd.CompressionParameters(window_log=windowlog,
                                       chain_log=chainlog,
                                       hash_log=hashlog,
                                       search_log=searchlog,
                                       min_match=searchlength,
                                       target_length=targetlength,
                                       compression_strategy=strategy)

        cctx = zstd.ZstdCompressor(compression_params=p)
        with cctx.write_to(io.BytesIO()):
            pass

    @hypothesis.given(s_windowlog, s_chainlog, s_hashlog, s_searchlog,
                        s_searchlength, s_targetlength, s_strategy)
    def test_estimated_compression_context_size(self, windowlog, chainlog,
                                                hashlog, searchlog,
                                                searchlength, targetlength,
                                                strategy):
        if searchlength == zstd.SEARCHLENGTH_MIN and strategy in (zstd.STRATEGY_FAST, zstd.STRATEGY_GREEDY):
            searchlength += 1
        elif searchlength == zstd.SEARCHLENGTH_MAX and strategy != zstd.STRATEGY_FAST:
            searchlength -= 1

        p = zstd.CompressionParameters(window_log=windowlog,
                                       chain_log=chainlog,
                                       hash_log=hashlog,
                                       search_log=searchlog,
                                       min_match=searchlength,
                                       target_length=targetlength,
                                       compression_strategy=strategy)
        size = p.estimated_compression_context_size()


@@ -1982,858 +1982,8 @@
     
- # ZSTD_checkCParams moves the goal posts on us from what's advertised%0A        # in the constants. So move along with them.%0A        if searchlength == zstd.SEARCHLENGTH_MIN and strategy in (zstd.STRATEGY_FAST, zstd.STRATEGY_GREEDY):%0A            searchlength += 1%0A        elif searchlength == zstd.SEARCHLENGTH_MAX and strategy != zstd.STRATEGY_FAST:%0A            searchlength -= 1%0A%0A        # 32-bit machines may have trouble allocating larger sizes. So cap%0A        # them. This reduces test coverage for this machine type. But 64-bit%0A        # should still have us covered.%0A        maxint = sys.maxint if hasattr(sys, 'maxint') else sys.maxsize%0A        if maxint %3C= 2**32:%0A            windowlog = min(windowlog, 25)%0A            hashlog = min(hashlog, 25)%0A            chainlog = min(chainlog, 26)%0A            searchlog = min(searchlog, 24)%0A%0A        p =
  zst
@@ -2055,36 +2055,32 @@
                 
-   
- 
 chain_log=chainl
@@ -2110,36 +2110,32 @@
                 
-    
 hash_log=hashlog
@@ -2163,36 +2163,32 @@
                 
-   
- 
 search_log=searc
@@ -2185,36 +2185,32 @@
 _log=searchlog,%0A
-    
                 
@@ -2279,36 +2279,32 @@
                 
-  
-  
 target_length=ta
@@ -2307,36 +2307,32 @@
 h=targetlength,%0A
-    
                 
@@ -2386,125 +2386,8 @@
 y)%0A%0A
-        cctx = zstd.ZstdCompressor(compression_params=p)%0A        with cctx.write_to(io.BytesIO()):%0A            pass%0A%0A
     

update CompressionParameters fuzzing test