code: def test_with_one_shuffle(func_name, func_opts):
      # only 1 axis is monotonic
      # data1 with index split into [0...4], [5...9],
      data1 = pd.DataFrame(
          np.random.rand(10, 10),
          index=np.arange(10),
          columns=[4, 1, 3, 2, 10, 5, 9, 8, 6, 7],
      )
      data1 = to_boolean_if_needed(func_opts.func_name, data1)
      df1 = from_pandas(data1, chunk_size=5)
      # data2 with index split into [6...11], [2, 5],
      data2 = pd.DataFrame(
          np.random.rand(10, 10),
          index=np.arange(11, 1, -1),
          columns=[5, 9, 12, 3, 11, 10, 6, 4, 1, 2],
      )
      data2 = to_boolean_if_needed(func_opts.func_name, data2)
      df2 = from_pandas(data2, chunk_size=6)
  
      df3 = func_opts.func(df1, df2)
  
      # test df3's index and columns
      pd.testing.assert_index_equal(
          df3.columns_value.to_pandas(),
          func_opts.func(data1, data2).columns,
      )
      assert isinstance(df3.index_value.value, IndexValue.Int64Index)
      pd.testing.assert_index_equal(
          df3.index_value.to_pandas(), pd.Index([], dtype=np.int64)
      )
      assert df3.index_value.key != df1.index_value.key
      assert df3.index_value.key != df2.index_value.key
      assert df3.shape[1] == 12  # columns is recorded, so we can get it
  
      df1, df2, df3 = tile(df1, df2, df3)
  
      data1_index_min_max = [(0, True, 4, True), (5, True, 9, True)]
      data2_index_min_max = [(2, True, 5, True), (6, True, 11, True)]
  
      (
          left_index_splits,
          right_index_splits,
      ) = split_monotonic_index_min_max(
          data1_index_min_max, True, data2_index_min_max, False
      )
  
      left_index_idx_to_original_idx = build_split_idx_to_origin_idx(
          left_index_splits
      )
      right_index_idx_to_original_idx = build_split_idx_to_origin_idx(
          right_index_splits, False
      )
  
      assert df3.chunk_shape == (7, 2)
      for c in df3.chunks:
          assert isinstance(c.op, func_opts.op)
          assert len(c.inputs) == 2
          idx = c.index
          # test the left side
          assert isinstance(c.inputs[0].op, DataFrameIndexAlign)
          assert c.inputs[0].op.stage == OperandStage.reduce
          expect_dtypes = pd.concat(
              [
                  hash_dtypes(ic.inputs[0].op.data.dtypes, 2)[
                      c.index[1]
                  ]
                  for ic in c.inputs[0].inputs[0].inputs
              ]
          )
          pd.testing.assert_series_equal(
              c.inputs[0].dtypes, expect_dtypes
          )
          pd.testing.assert_index_equal(
              c.inputs[0].columns_value.to_pandas(),
              c.inputs[0].dtypes.index,
          )
          assert isinstance(
              c.inputs[0].index_value.to_pandas(), type(data1.index)
          )
          assert isinstance(
              c.inputs[0].inputs[0].op, DataFrameShuffleProxy
          )
          (
              left_row_idx,
              left_row_inner_idx,
          ) = left_index_idx_to_original_idx[idx[0]]
          left_index_min_max = left_index_splits[left_row_idx][
              left_row_inner_idx
          ]
          ics = [ic for ic in df1.chunks if ic.index[0] == left_row_idx]
          for j, ci, ic in zip(
              itertools.count(0), c.inputs[0].inputs[0].inputs, ics
          ):
              assert isinstance(ci.op, DataFrameIndexAlign)
              assert ci.op.stage == OperandStage.map
              assert ci.index == (idx[0], j)
              assert ci.op.index_min == left_index_min_max[0]
              assert ci.op.index_min_close == left_index_min_max[1]
              assert ci.op.index_max == left_index_min_max[2]
              assert ci.op.index_max_close == left_index_min_max[3]
              assert isinstance(
                  ci.index_value.to_pandas(), type(data1.index)
              )
              assert ci.op.column_shuffle_size
              shuffle_segments = ci.op.column_shuffle_segments
              expected_shuffle_segments = hash_dtypes(ic.data.dtypes, 2)
              assert len(shuffle_segments) == len(
                  expected_shuffle_segments
              )
              for ss, ess in zip(
                  shuffle_segments, expected_shuffle_segments
              ):
                  pd.testing.assert_series_equal(ss, ess)
              assert ci.inputs[0] is ic.data
          # test the right side
          assert isinstance(c.inputs[1].op, DataFrameIndexAlign)
          assert c.inputs[1].op.stage == OperandStage.reduce
          expect_dtypes = pd.concat(
              [
                  hash_dtypes(ic.inputs[0].op.data.dtypes, 2)[
                      c.index[1]
                  ]
                  for ic in c.inputs[1].inputs[0].inputs
              ]
          )
          pd.testing.assert_series_equal(
              c.inputs[1].dtypes, expect_dtypes
          )
          pd.testing.assert_index_equal(
              c.inputs[1].columns_value.to_pandas(),
              c.inputs[1].dtypes.index,
          )
          assert isinstance(
              c.inputs[1].index_value.to_pandas(), type(data1.index)
          )
          assert isinstance(
              c.inputs[1].inputs[0].op, DataFrameShuffleProxy
          )
          (
              right_row_idx,
              right_row_inner_idx,
          ) = right_index_idx_to_original_idx[idx[0]]
          right_index_min_max = right_index_splits[right_row_idx][
              right_row_inner_idx
          ]
          ics = [
              ic for ic in df2.chunks if ic.index[0] == right_row_idx
          ]
          for j, ci, ic in zip(
              itertools.count(0), c.inputs[1].inputs[0].inputs, ics
          ):
              assert isinstance(ci.op, DataFrameIndexAlign)
              assert ci.op.stage == OperandStage.map
              assert ci.index == (idx[0], j)
              assert ci.op.index_min == right_index_min_max[0]
              assert ci.op.index_min_close == right_index_min_max[1]
              assert ci.op.index_max == right_index_min_max[2]
              assert ci.op.index_max_close == right_index_min_max[3]
              assert ci.op.column_shuffle_size
              shuffle_segments = ci.op.column_shuffle_segments
              expected_shuffle_segments = hash_dtypes(ic.data.dtypes, 2)
              assert len(shuffle_segments) == len(
                  expected_shuffle_segments
              )
              for ss, ess in zip(
                  shuffle_segments, expected_shuffle_segments
              ):
                  pd.testing.assert_series_equal(ss, ess)
              assert ci.inputs[0] is ic.data
  
      # make sure shuffle proxies' key are different
      proxy_keys = set()
      for i in range(df3.chunk_shape[0]):
          cs = [c for c in df3.chunks if c.index[0] == i]
          lps = {c.inputs[0].inputs[0].op.key for c in cs}
          assert len(lps) == 1
          proxy_keys.add(lps.pop())
          rps = {c.inputs[1].inputs[0].op.key for c in cs}
          assert len(rps) == 1
          proxy_keys.add(rps.pop())
      assert len(proxy_keys) == 2 * df3.chunk_shape[0]
  
imports: import datetime
  import itertools
  import operator
  from dataclasses import dataclass
  from typing import Callable
  import numpy
  import pandas
  import pytest
  from ....None import tensor
  from ....core import OutputType, OperandType, tile
  from ....core.operand import OperandStage
  from ....utils import dataslots
  from ...align import DataFrameIndexAlign, DataFrameShuffleProxy
  from ...core import IndexValue
  from ...datasource.dataframe import from_pandas, DataFrameDataSource
  from ...datasource.from_tensor import dataframe_from_tensor
  from ...datasource.series import from_pandas, SeriesDataSource
  from ...utils import hash_dtypes
  from ...utils import split_monotonic_index_min_max, build_split_idx_to_origin_idx, filter_index_value
  from ..None import DataFrameAbs, DataFrameAdd, DataFrameSubtract, DataFrameMul, DataFrameFloorDiv, DataFrameTrueDiv, DataFrameMod, DataFramePower, DataFrameEqual, DataFrameNotEqual, DataFrameGreater, DataFrameLess, DataFrameGreaterEqual, DataFrameLessEqual, DataFrameNot, DataFrameAnd, DataFrameOr, DataFrameXor
label_desc: Use image node_id 11 for calling a global function with example usage: test_with_one_shuffle(func_name, func_opts) without return types