class TestUnit(TestCase):


    @given(sfst.get_labels())  # type: ignore
    def test_get_labels(self, values: tp.Iterable[tp.Hashable]) -> None:
        for value in values:
            self.assertTrue(isinstance(hash(value), int))

    @given(sfst.get_dtypes())  # type: ignore
    def test_get_dtypes(self, dtypes: tp.Iterable[np.dtype]) -> None:
        for dt in dtypes:
            self.assertTrue(isinstance(dt, np.dtype))

    @given(sfst.get_spacing(10))  # type: ignore
    def test_get_spacing_10(self, spacing: tp.Iterable[int]) -> None:
        self.assertEqual(sum(spacing), 10)

    @hypo_settings(max_examples=10)  # type: ignore
    @given(sfst.get_shape_1d2d())  # type: ignore
    def test_get_shape_1d2d(self, shape: tp.Tuple[int, ...]) -> None:
        self.assertTrue(isinstance(shape, tuple))
        self.assertTrue(len(shape) in (1, 2))

    @hypo_settings(max_examples=10)  # type: ignore
    @given(sfst.get_array_1d2d())  # type: ignore
    def test_get_array_1d2d(self, array: np.ndarray) -> None:
        self.assertTrue(isinstance(array, np.ndarray))
        self.assertTrue(array.ndim in (1, 2))

    @hypo_settings(max_examples=10)  # type: ignore
    @given(sfst.get_arrays_2d_aligned_columns(min_size=2))  # type: ignore
    def test_get_arrays_2s_aligned_columns(self, arrays: tp.Iterable[np.ndarray]) -> None:
        array_iter = iter(arrays)
        a1 = next(array_iter)
        match = a1.shape[1]
        for array in array_iter:
            self.assertEqual(array.shape[1], match)

    @given(sfst.get_arrays_2d_aligned_rows(min_size=2))  # type: ignore
    def test_get_arrays_2s_aligned_rows(self, arrays: tp.Iterable[np.ndarray]) -> None:
        array_iter = iter(arrays)
        a1 = next(array_iter)
        match = a1.shape[0]
        for array in array_iter:
            self.assertEqual(array.shape[0], match)

    @hypo_settings(max_examples=10)  # type: ignore
    @given(sfst.get_blocks())  # type: ignore
    def test_get_blocks(self, blocks: tp.Tuple[np.ndarray]) -> None:
        self.assertTrue(isinstance(blocks, tuple))
        for b in blocks:
            self.assertTrue(isinstance(b, np.ndarray))
            self.assertTrue(b.ndim in (1, 2))

    @hypo_settings(max_examples=10)  # type: ignore
    @given(sfst.get_type_blocks())  # type: ignore
    def test_get_type_blocks(self, tb: TypeBlocks) -> None:
        self.assertTrue(isinstance(tb, TypeBlocks))
        rows, cols = tb.shape
        col_count = 0
        for b in tb._blocks:
            if b.ndim == 1:
                self.assertEqual(len(b), rows)
                col_count += 1
            else:
                self.assertEqual(b.ndim, 2)
                self.assertEqual(b.shape[0], rows)
                col_count += b.shape[1]

        self.assertEqual(col_count, cols)

    @hypo_settings(max_examples=10) # type: ignore
    @given(sfst.get_index()) # type: ignore
    def test_get_index(self, idx: Index) -> None:
        self.assertTrue(isinstance(idx, Index))
        self.assertEqual(len(idx), len(idx.values))

    @hypo_settings(max_examples=10)  # type: ignore
    @given(sfst.get_index_hierarchy()) # type: ignore
    def test_get_index_hierarchy(self, idx: IndexHierarchy) -> None:
        self.assertTrue(isinstance(idx, IndexHierarchy))
        self.assertTrue(idx.depth > 1)
        self.assertEqual(len(idx), len(idx.values))

    @hypo_settings(max_examples=10)  # type: ignore
    @given(sfst.get_series())  # type: ignore
    def test_get_series(self, series: Series) -> None:
        self.assertTrue(isinstance(series, Series))
        self.assertEqual(len(series), len(series.values))

    @hypo_settings(max_examples=10)  # type: ignore
    @given(sfst.get_frame())  # type: ignore
    def test_get_frame(self, frame: Frame) -> None:
        self.assertTrue(isinstance(frame, Frame))
        self.assertEqual(frame.shape, frame.values.shape)

    @hypo_settings(max_examples=10)  # type: ignore
    @given(sfst.get_frame(index_cls=IndexHierarchy, columns_cls=IndexHierarchy))  # type: ignore
    def test_get_frame_hierarchy(self, frame: Frame) -> None:
        self.assertTrue(isinstance(frame, Frame))
        self.assertTrue(frame.index.depth > 1)
        self.assertTrue(frame.columns.depth > 1)
        self.assertEqual(frame.shape, frame.values.shape)
class TestUnit(TestCase):
    @given(sfst.get_series())
    def test_basic_attributes(self, s1: Series) -> None:

        self.assertEqual(s1.dtype, s1.values.dtype)
        # self.assertEqual(s1.shape, s1.shape)
        self.assertEqual(s1.ndim, 1)

        if s1.shape[0] > 0:
            self.assertTrue(s1.size > 0)
            self.assertTrue(s1.nbytes > 0)

    @given(sfst.get_series(dtype_group=sfst.DTGroup.NUMERIC, min_size=1))
    def test_unary_operators_numeric(self, s1: Series) -> None:
        for op in _UFUNC_UNARY_OPERATORS:
            if op == '__invert__':  # invalid on non Boolean
                continue
            func = getattr(operator, op)
            a = func(s1).values
            b = func(s1.values)
            self.assertAlmostEqualArray(a, b)

    @given(sfst.get_series(dtype_group=sfst.DTGroup.BOOL, min_size=1))
    def test_unary_operators_boolean(self, s1: Series) -> None:
        for op in _UFUNC_UNARY_OPERATORS:
            if op != '__invert__':  # valid on Boolean
                continue
            func = getattr(operator, op)
            a = func(s1).values
            b = func(s1.values)
            self.assertAlmostEqualArray(a, b)

    @given(sfst.get_series(dtype_group=sfst.DTGroup.NUMERIC))
    def test_binary_operators_numeric(self, s1: Series) -> None:
        for op in _UFUNC_BINARY_OPERATORS:
            if op in {
                    '__matmul__',
                    '__pow__',
                    '__lshift__',
                    '__rshift__',
                    '__and__',
                    '__xor__',
                    '__or__',
                    '__mod__',
            }:
                continue
            func = getattr(operator, op)
            values = s1.values
            a = func(s1, s1).values
            b = func(values, values)
            self.assertAlmostEqualArray(a, b)

    @given(sfst.get_series(dtype_group=sfst.DTGroup.BOOL))
    def test_binary_operators_boolean(self, s1: Series) -> None:
        for op in _UFUNC_BINARY_OPERATORS:
            if op not in {
                    '__and__',
                    '__xor__',
                    '__or__',
            }:
                continue
            func = getattr(operator, op)
            values = s1.values
            a = func(s1, s1).values
            b = func(values, values)
            self.assertAlmostEqualArray(a, b)

    @given(sfst.get_series(dtype_group=sfst.DTGroup.NUMERIC, min_size=1))
    def test_ufunc_axis(self, s1: Series) -> None:
        for attr, attrs in UFUNC_AXIS_SKIPNA.items():
            a = getattr(s1, attr)()
            func = attrs.ufunc_skipna
            b = func(s1.values)
            self.assertEqualWithNaN(a, b)

    @given(sfst.get_series(min_size=1))
    def test_isin(self, s1: Series) -> None:

        value = s1.iloc[0]
        if not isna_element(value):
            self.assertTrue(s1.isin((value, )).iloc[0])