Repository: modin-project/modin

Issue:
Enable test_join_sort test on the HDK engine and add to CI
Currently, there are 393 failures, when the test is running on the HDK engine. All these failures should be fixed and the test added to CI.
``where`` doesn`t work correctly at MODIN_STORAGE_FORMAT=omnisci
When I run at MODIN_STORAGE_FORMAT=omnisci:
```
import numpy as np
import modin.pandas as pd
frame_data = np.random.RandomState(seed=42).randn(100)
modin_series = pd.Series(frame_data)
modin_cond_series = modin_series % 5 < 2
modin_result = modin_series.where(modin_cond_series, -modin_series)
```
I have error:
```
RuntimeError: TException - service has thrown: TOmniSciException(error_msg=non-integer operands in modulo 
operation.)
```


Discussion:

@modin-project/modin-omnisci  could someone please check if this still happens?

Resolving patch:
diff --git a/modin/experimental/core/execution/native/implementations/hdk_on_native/dataframe/dataframe.py b/modin/experimental/core/execution/native/implementations/hdk_on_native/dataframe/dataframe.py
--- a/modin/experimental/core/execution/native/implementations/hdk_on_native/dataframe/dataframe.py
+++ b/modin/experimental/core/execution/native/implementations/hdk_on_native/dataframe/dataframe.py
@@ -21,7 +21,12 @@
 from modin.experimental.core.storage_formats.hdk.query_compiler import (
     DFAlgQueryCompiler,
 )
-from .utils import LazyProxyCategoricalDtype
+from .utils import (
+    LazyProxyCategoricalDtype,
+    check_join_supported,
+    check_cols_to_join,
+    get_data_for_join_by_index,
+)
 from ..partitioning.partition_manager import HdkOnNativeDataframePartitionManager
 
 from pandas.core.indexes.api import ensure_index, Index, MultiIndex, RangeIndex
@@ -853,7 +858,7 @@ def join(
         HdkOnNativeDataframe
             The new frame.
         """
-        how = JoinType(how)
+        check_join_supported(how)
         assert (
             left_on is not None and right_on is not None
         ), "Merge with unspecified 'left_on' or 'right_on' parameter is not supported in the engine"
@@ -861,51 +866,61 @@ def join(
             right_on
         ), "'left_on' and 'right_on' lengths don't match"
 
-        for col in left_on:
-            assert col in self.columns, f"'left_on' references unknown column {col}"
-        for col in right_on:
-            assert col in other.columns, f"'right_on' references unknown column {col}"
-
-        new_columns = []
-        new_dtypes = []
-        exprs = OrderedDict()
+        orig_left_on = left_on
+        orig_right_on = right_on
+        left, left_on = check_cols_to_join("left_on", self, left_on)
+        right, right_on = check_cols_to_join("right_on", other, right_on)
 
-        left_conflicts = set(self.columns) & (set(other.columns) - set(right_on))
-        right_conflicts = set(other.columns) & (set(self.columns) - set(left_on))
-        conflicting_cols = left_conflicts | right_conflicts
-        for c in self.columns:
-            new_name = f"{c}{suffixes[0]}" if c in conflicting_cols else c
-            new_columns.append(new_name)
-            new_dtypes.append(self._dtypes[c])
-            exprs[new_name] = self.ref(c)
-        for c in other.columns:
-            if c not in left_on or c not in right_on:
-                new_name = f"{c}{suffixes[1]}" if c in conflicting_cols else c
+        # If either left_on or right_on has been changed, it means that there
+        # are index columns in the list. Joining by index in this case.
+        if (left_on is not orig_left_on) or (right_on is not orig_right_on):
+            index_cols, exprs, new_dtypes, new_columns = get_data_for_join_by_index(
+                self, other, how, orig_left_on, orig_right_on, sort, suffixes
+            )
+            ignore_index = False
+        else:
+            ignore_index = True
+            index_cols = None
+            exprs = OrderedDict()
+            new_dtypes = []
+            new_columns = []
+            left_conflicts = set(left.columns) & (set(right.columns) - set(right_on))
+            right_conflicts = set(right.columns) & (set(left.columns) - set(left_on))
+            conflicting_cols = left_conflicts | right_conflicts
+            for c in left.columns:
+                new_name = f"{c}{suffixes[0]}" if c in conflicting_cols else c
                 new_columns.append(new_name)
-                new_dtypes.append(other._dtypes[c])
-                exprs[new_name] = other.ref(c)
-
-        condition = self._build_equi_join_condition(other, left_on, right_on)
+                new_dtypes.append(left._dtypes[c])
+                exprs[new_name] = left.ref(c)
+            for c in right.columns:
+                if c not in left_on or c not in right_on:
+                    new_name = f"{c}{suffixes[1]}" if c in conflicting_cols else c
+                    new_columns.append(new_name)
+                    new_dtypes.append(right._dtypes[c])
+                    exprs[new_name] = right.ref(c)
+            new_columns = Index.__new__(Index, data=new_columns)
+
+        condition = left._build_equi_join_condition(right, left_on, right_on)
 
         op = JoinNode(
-            self,
-            other,
-            how=how.value,
+            left,
+            right,
+            how=how,
             exprs=exprs,
             condition=condition,
         )
 
-        new_columns = Index.__new__(Index, data=new_columns)
-        res = self.__constructor__(
+        res = left.__constructor__(
             dtypes=new_dtypes,
             columns=new_columns,
+            index_cols=index_cols,
             op=op,
             force_execution_mode=self._force_execution_mode,
         )
 
         if sort:
             res = res.sort_rows(
-                left_on, ascending=True, ignore_index=True, na_position="last"
+                left_on, ascending=True, ignore_index=ignore_index, na_position="last"
             )
 
         return res
@@ -1290,9 +1305,7 @@ def _join_by_index(self, other_modin_frames, how, sort, ignore_index):
         HdkOnNativeDataframe
             The new frame.
         """
-        if how == "outer":
-            raise NotImplementedError("outer join is not supported in HDK engine")
-
+        check_join_supported(how)
         lhs = self._maybe_materialize_rowid()
         reset_index_names = False
         for rhs in other_modin_frames:
@@ -1618,9 +1631,16 @@ def sort_rows(self, columns, ascending, ignore_index, na_position):
         if na_position != "first" and na_position != "last":
             raise ValueError(f"Unsupported na_position value '{na_position}'")
 
+        base = self
+
+        # If index is preserved and we have no index columns then we
+        # need to create one using __rowid__ virtual column.
+        if not ignore_index and base._index_cols is None:
+            base = base._materialize_rowid()
+
         if not isinstance(columns, list):
             columns = [columns]
-        columns = [self._find_index_or_col(col) for col in columns]
+        columns = [base._find_index_or_col(col) for col in columns]
 
         if isinstance(ascending, list):
             if len(ascending) != len(columns):
@@ -1634,14 +1654,12 @@ def sort_rows(self, columns, ascending, ignore_index, na_position):
             # If index is ignored then we might need to drop some columns.
             # At the same time some of dropped index columns can be used
             # for sorting and should be droped after sorting is done.
-            if self._index_cols is not None:
-                base = self
-
+            if base._index_cols is not None:
                 drop_index_cols_before = [
-                    col for col in self._index_cols if col not in columns
+                    col for col in base._index_cols if col not in columns
                 ]
                 drop_index_cols_after = [
-                    col for col in self._index_cols if col in columns
+                    col for col in base._index_cols if col in columns
                 ]
                 if not drop_index_cols_after:
                     drop_index_cols_after = None
@@ -1655,57 +1673,50 @@ def sort_rows(self, columns, ascending, ignore_index, na_position):
                         exprs[col] = base.ref(col)
                     for col in base.columns:
                         exprs[col] = base.ref(col)
-                    base = self.__constructor__(
+                    base = base.__constructor__(
                         columns=base.columns,
-                        dtypes=self._dtypes_for_exprs(exprs),
+                        dtypes=base._dtypes_for_exprs(exprs),
                         op=TransformNode(base, exprs),
                         index_cols=index_cols,
-                        force_execution_mode=self._force_execution_mode,
+                        force_execution_mode=base._force_execution_mode,
                     )
 
-                base = self.__constructor__(
+                base = base.__constructor__(
                     columns=base.columns,
                     dtypes=base._dtypes,
                     op=SortNode(base, columns, ascending, na_position),
                     index_cols=base._index_cols,
-                    force_execution_mode=self._force_execution_mode,
+                    force_execution_mode=base._force_execution_mode,
                 )
 
                 if drop_index_cols_after:
                     exprs = OrderedDict()
                     for col in base.columns:
                         exprs[col] = base.ref(col)
-                    base = self.__constructor__(
+                    base = base.__constructor__(
                         columns=base.columns,
-                        dtypes=self._dtypes_for_exprs(exprs),
+                        dtypes=base._dtypes_for_exprs(exprs),
                         op=TransformNode(base, exprs),
                         index_cols=None,
-                        force_execution_mode=self._force_execution_mode,
+                        force_execution_mode=base._force_execution_mode,
                     )
 
                 return base
             else:
-                return self.__constructor__(
-                    columns=self.columns,
-                    dtypes=self._dtypes,
-                    op=SortNode(self, columns, ascending, na_position),
+                return base.__constructor__(
+                    columns=base.columns,
+                    dtypes=base._dtypes,
+                    op=SortNode(base, columns, ascending, na_position),
                     index_cols=None,
-                    force_execution_mode=self._force_execution_mode,
+                    force_execution_mode=base._force_execution_mode,
                 )
         else:
-            base = self
-
-            # If index is preserved and we have no index columns then we
-            # need to create one using __rowid__ virtual column.
-            if self._index_cols is None:
-                base = base._materialize_rowid()
-
-            return self.__constructor__(
+            return base.__constructor__(
                 columns=base.columns,
                 dtypes=base._dtypes,
                 op=SortNode(base, columns, ascending, na_position),
                 index_cols=base._index_cols,
-                force_execution_mode=self._force_execution_mode,
+                force_execution_mode=base._force_execution_mode,
             )
 
     def filter(self, key):
@@ -1802,15 +1813,17 @@ def _materialize_rowid(self):
         HdkOnNativeDataframe
             The new frame.
         """
+        name = None if self._index_cache is None else self._index_cache.name
+        name = "__index__" if name is None else self._mangle_index_names([name])[0]
         exprs = OrderedDict()
-        exprs["__index__"] = self.ref("__rowid__")
+        exprs[name] = self.ref("__rowid__")
         for col in self._table_cols:
             exprs[col] = self.ref(col)
         return self.__constructor__(
             columns=self.columns,
             dtypes=self._dtypes_for_exprs(exprs),
             op=TransformNode(self, exprs),
-            index_cols=["__index__"],
+            index_cols=[name],
             uses_rowid=True,
             force_execution_mode=self._force_execution_mode,
         )
@@ -2396,6 +2409,8 @@ def get_index_name(self):
         -------
         str or None
         """
+        if self._index_cache is not None:
+            return self._index_cache.name
         if self._index_cols is None:
             return None
         if len(self._index_cols) > 1:
@@ -2452,6 +2467,8 @@ def get_index_names(self):
         -------
         list of str
         """
+        if self._index_cache is not None:
+            return self._index_cache.names
         if self.has_multiindex():
             return self._index_cols.copy()
         return [self.get_index_name()]
diff --git a/modin/experimental/core/execution/native/implementations/hdk_on_native/dataframe/utils.py b/modin/experimental/core/execution/native/implementations/hdk_on_native/dataframe/utils.py
--- a/modin/experimental/core/execution/native/implementations/hdk_on_native/dataframe/utils.py
+++ b/modin/experimental/core/execution/native/implementations/hdk_on_native/dataframe/utils.py
@@ -13,6 +13,7 @@
 
 """Utilities for internal use by the ``HdkOnNativeDataframe``."""
 
+from collections import OrderedDict
 
 import pandas
 import pyarrow
@@ -78,3 +79,172 @@ def _categories(self):  # noqa: GL08
     def _set_categories(self, categories):  # noqa: GL08
         self._lazy_categories = categories
         self._table = None
+
+
+def check_join_supported(join_type: str):
+    """
+    Check if join type is supported by HDK.
+
+    Parameters
+    ----------
+    join_type : str
+        Join type.
+
+    Returns
+    -------
+    None
+    """
+    if join_type not in ("inner", "left"):
+        raise NotImplementedError(
+            f"{join_type} join is not supported by the HDK engine"
+        )
+
+
+def check_cols_to_join(what, df, col_names):
+    """
+    Check the frame columns.
+
+    Check if the frame (`df`) has the specified columns (`col_names`). The names referring to
+    the index columns are replaced with the actual index column names.
+
+    Parameters
+    ----------
+    what : str
+        Attribute name.
+    df : HdkOnNativeDataframe
+        The dataframe.
+    col_names : list of str
+        The column names to check.
+
+    Returns
+    -------
+    Tuple[HdkOnNativeDataframe, list]
+        The aligned data frame and column names.
+    """
+    cols = df.columns
+    new_col_names = col_names
+    for i, col in enumerate(col_names):
+        if col in cols:
+            continue
+        new_name = None
+        if df._index_cols is not None:
+            for c in df._index_cols:
+                if col == df._index_name(c):
+                    new_name = c
+                    break
+        elif df._index_cache is not None:
+            new_name = f"__index__{0}_{col}"
+            df = df._maybe_materialize_rowid()
+        if new_name is None:
+            raise ValueError(f"'{what}' references unknown column {col}")
+        if new_col_names is col_names:
+            # We are replacing the index names in the original list,
+            # but creating a copy.
+            new_col_names = col_names.copy()
+        new_col_names[i] = new_name
+    return df, new_col_names
+
+
+def get_data_for_join_by_index(
+    left,
+    right,
+    how,
+    left_on,
+    right_on,
+    sort,
+    suffixes,
+):
+    """
+    Return the column names, dtypes and expres, required for join by index.
+
+    This is a helper function, used by `HdkOnNativeDataframe.join()`, when joining by index.
+
+    Parameters
+    ----------
+    left : HdkOnNativeDataframe
+        A frame to join.
+    right : HdkOnNativeDataframe
+        A frame to join with.
+    how : str
+        A type of join.
+    left_on : list of str
+        A list of columns for the left frame to join on.
+    right_on : list of str
+        A list of columns for the right frame to join on.
+    sort : bool
+        Sort the result by join keys.
+    suffixes : list-like of str
+        A length-2 sequence of suffixes to add to overlapping column names
+        of left and right operands respectively.
+
+    Returns
+    -------
+    tuple
+
+    The index columns, exprs, dtypes and columns.
+    """
+
+    def to_empty_pandas_df(df):
+        # Create an empty pandas frame with the same columns and index.
+        idx = df._index_cache
+        if idx is not None:
+            idx = idx[:1]
+        elif df._index_cols is not None:
+            if len(df._index_cols) > 1:
+                arrays = [[i] for i in range(len(df._index_cols))]
+                names = [df._index_name(n) for n in df._index_cols]
+                idx = pandas.MultiIndex.from_arrays(arrays, names=names)
+            else:
+                idx = pandas.Index(name=df._index_name(df._index_cols[0]))
+        return pandas.DataFrame(columns=df.columns, index=idx)
+
+    new_dtypes = []
+    exprs = OrderedDict()
+    merged = to_empty_pandas_df(left).merge(
+        to_empty_pandas_df(right),
+        how=how,
+        left_on=left_on,
+        right_on=right_on,
+        sort=sort,
+        suffixes=suffixes,
+    )
+
+    if len(merged.index.names) == 1 and (merged.index.names[0] is None):
+        index_cols = None
+    else:
+        index_cols = left._mangle_index_names(merged.index.names)
+        for orig_name, mangled_name in zip(merged.index.names, index_cols):
+            # Using _dtypes here since it contains all column names,
+            # including the index.
+            df = left if mangled_name in left._dtypes else right
+            exprs[orig_name] = df.ref(mangled_name)
+            new_dtypes.append(df._dtypes[mangled_name])
+
+    left_col_names = set(left.columns)
+    right_col_names = set(right.columns)
+    for col in merged.columns:
+        orig_name = col
+        if orig_name in left_col_names:
+            df = left
+        elif orig_name in right_col_names:
+            df = right
+        elif suffixes is None:
+            raise ValueError(f"Unknown column {col}")
+        elif (
+            col.endswith(suffixes[0])
+            and (orig_name := col[0 : -len(suffixes[0])]) in left_col_names
+            and orig_name in right_col_names
+        ):
+            df = left  # Overlapping column from the left frame
+        elif (
+            col.endswith(suffixes[1])
+            and (orig_name := col[0 : -len(suffixes[1])]) in right_col_names
+            and orig_name in left_col_names
+        ):
+            df = right  # Overlapping column from the right frame
+        else:
+            raise ValueError(f"Unknown column {col}")
+        exprs[col] = df.ref(orig_name)
+        new_dtypes.append(df._dtypes[orig_name])
+
+    return index_cols, exprs, new_dtypes, merged.columns
diff --git a/modin/experimental/core/storage_formats/hdk/query_compiler.py b/modin/experimental/core/storage_formats/hdk/query_compiler.py
--- a/modin/experimental/core/storage_formats/hdk/query_compiler.py
+++ b/modin/experimental/core/storage_formats/hdk/query_compiler.py
@@ -661,7 +661,11 @@ def mul(self, other, **kwargs):
         return self._bin_op(other, "mul", **kwargs)
 
     def mod(self, other, **kwargs):
-        return self._bin_op(other, "mod", **kwargs)
+        int_codes = np.typecodes["AllInteger"]
+        if all(t.char in int_codes for t in self._modin_frame.dtypes):
+            return self._bin_op(other, "mod", **kwargs)
+        else:
+            raise NotImplementedError("Non-integer operands in modulo operation")
 
     def floordiv(self, other, **kwargs):
         return self._bin_op(other, "floordiv", **kwargs)
@@ -738,6 +742,9 @@ def insert(self, loc, column, value):
         return self.__constructor__(self._modin_frame.insert(loc, column, value))
 
     def sort_rows_by_column_values(self, columns, ascending=True, **kwargs):
+        if kwargs.get("key", None) is not None:
+            raise NotImplementedError("Sort with key function")
+
         ignore_index = kwargs.get("ignore_index", False)
         na_position = kwargs.get("na_position", "last")
         return self.__constructor__(


Test patch:
diff --git a/modin/experimental/core/execution/native/implementations/hdk_on_native/test/test_dataframe.py b/modin/experimental/core/execution/native/implementations/hdk_on_native/test/test_dataframe.py
--- a/modin/experimental/core/execution/native/implementations/hdk_on_native/test/test_dataframe.py
+++ b/modin/experimental/core/execution/native/implementations/hdk_on_native/test/test_dataframe.py
@@ -1538,179 +1538,179 @@ def applier(df1, df2, **kwargs):
         run_and_compare(applier, data=self.data, data2=self.data, force_lazy=False)
 
     def test_add_cst(self):
-        def add(lib, df):
+        def add(df, **kwargs):
             return df + 1
 
         run_and_compare(add, data=self.data)
 
     def test_add_list(self):
-        def add(lib, df):
+        def add(df, **kwargs):
             return df + [1, 2, 3, 4]
 
         run_and_compare(add, data=self.data)
 
     @pytest.mark.parametrize("fill_value", fill_values)
     def test_add_method_columns(self, fill_value):
-        def add1(lib, df, fill_value):
+        def add1(df, fill_value, **kwargs):
             return df["a"].add(df["b"], fill_value=fill_value)
 
-        def add2(lib, df, fill_value):
+        def add2(df, fill_value, **kwargs):
             return df[["a", "c"]].add(df[["b", "a"]], fill_value=fill_value)
 
         run_and_compare(add1, data=self.data, fill_value=fill_value)
         run_and_compare(add2, data=self.data, fill_value=fill_value)
 
     def test_add_columns(self):
-        def add1(lib, df):
+        def add1(df, **kwargs):
             return df["a"] + df["b"]
 
-        def add2(lib, df):
+        def add2(df, **kwargs):
             return df[["a", "c"]] + df[["b", "a"]]
 
         run_and_compare(add1, data=self.data)
         run_and_compare(add2, data=self.data)
 
     def test_add_columns_and_assign(self):
-        def add(lib, df):
+        def add(df, **kwargs):
             df["sum"] = df["a"] + df["b"]
             return df
 
         run_and_compare(add, data=self.data)
 
     def test_add_columns_and_assign_to_existing(self):
-        def add(lib, df):
+        def add(df, **kwargs):
             df["a"] = df["a"] + df["b"]
             return df
 
         run_and_compare(add, data=self.data)
 
     def test_mul_cst(self):
-        def mul(lib, df):
+        def mul(df, **kwargs):
             return df * 2
 
         run_and_compare(mul, data=self.data)
 
     def test_mul_list(self):
-        def mul(lib, df):
+        def mul(df, **kwargs):
             return df * [2, 3, 4, 5]
 
         run_and_compare(mul, data=self.data)
 
     @pytest.mark.parametrize("fill_value", fill_values)
     def test_mul_method_columns(self, fill_value):
-        def mul1(lib, df, fill_value):
+        def mul1(df, fill_value, **kwargs):
             return df["a"].mul(df["b"], fill_value=fill_value)
 
-        def mul2(lib, df, fill_value):
+        def mul2(df, fill_value, **kwargs):
             return df[["a", "c"]].mul(df[["b", "a"]], fill_value=fill_value)
 
         run_and_compare(mul1, data=self.data, fill_value=fill_value)
         run_and_compare(mul2, data=self.data, fill_value=fill_value)
 
     def test_mul_columns(self):
-        def mul1(lib, df):
+        def mul1(df, **kwargs):
             return df["a"] * df["b"]
 
-        def mul2(lib, df):
+        def mul2(df, **kwargs):
             return df[["a", "c"]] * df[["b", "a"]]
 
         run_and_compare(mul1, data=self.data)
         run_and_compare(mul2, data=self.data)
 
     def test_mod_cst(self):
-        def mod(lib, df):
+        def mod(df, **kwargs):
             return df % 2
 
         run_and_compare(mod, data=self.data)
 
     def test_mod_list(self):
-        def mod(lib, df):
+        def mod(df, **kwargs):
             return df % [2, 3, 4, 5]
 
         run_and_compare(mod, data=self.data)
 
     @pytest.mark.parametrize("fill_value", fill_values)
     def test_mod_method_columns(self, fill_value):
-        def mod1(lib, df, fill_value):
+        def mod1(df, fill_value, **kwargs):
             return df["a"].mod(df["b"], fill_value=fill_value)
 
-        def mod2(lib, df, fill_value):
+        def mod2(df, fill_value, **kwargs):
             return df[["a", "c"]].mod(df[["b", "a"]], fill_value=fill_value)
 
         run_and_compare(mod1, data=self.data, fill_value=fill_value)
         run_and_compare(mod2, data=self.data, fill_value=fill_value)
 
     def test_mod_columns(self):
-        def mod1(lib, df):
+        def mod1(df, **kwargs):
             return df["a"] % df["b"]
 
-        def mod2(lib, df):
+        def mod2(df, **kwargs):
             return df[["a", "c"]] % df[["b", "a"]]
 
         run_and_compare(mod1, data=self.data)
         run_and_compare(mod2, data=self.data)
 
     def test_truediv_cst(self):
-        def truediv(lib, df):
+        def truediv(df, **kwargs):
             return df / 2
 
         run_and_compare(truediv, data=self.data)
 
     def test_truediv_list(self):
-        def truediv(lib, df):
+        def truediv(df, **kwargs):
             return df / [1, 0.5, 0.2, 2.0]
 
         run_and_compare(truediv, data=self.data)
 
     @pytest.mark.parametrize("fill_value", fill_values)
     def test_truediv_method_columns(self, fill_value):
-        def truediv1(lib, df, fill_value):
+        def truediv1(df, fill_value, **kwargs):
             return df["a"].truediv(df["b"], fill_value=fill_value)
 
-        def truediv2(lib, df, fill_value):
+        def truediv2(df, fill_value, **kwargs):
             return df[["a", "c"]].truediv(df[["b", "a"]], fill_value=fill_value)
 
         run_and_compare(truediv1, data=self.data, fill_value=fill_value)
         run_and_compare(truediv2, data=self.data, fill_value=fill_value)
 
     def test_truediv_columns(self):
-        def truediv1(lib, df):
+        def truediv1(df, **kwargs):
             return df["a"] / df["b"]
 
-        def truediv2(lib, df):
+        def truediv2(df, **kwargs):
             return df[["a", "c"]] / df[["b", "a"]]
 
         run_and_compare(truediv1, data=self.data)
         run_and_compare(truediv2, data=self.data)
 
     def test_floordiv_cst(self):
-        def floordiv(lib, df):
+        def floordiv(df, **kwargs):
             return df // 2
 
         run_and_compare(floordiv, data=self.data)
 
     def test_floordiv_list(self):
-        def floordiv(lib, df):
+        def floordiv(df, **kwargs):
             return df // [1, 0.54, 0.24, 2.01]
 
         run_and_compare(floordiv, data=self.data)
 
     @pytest.mark.parametrize("fill_value", fill_values)
     def test_floordiv_method_columns(self, fill_value):
-        def floordiv1(lib, df, fill_value):
+        def floordiv1(df, fill_value, **kwargs):
             return df["a"].floordiv(df["b"], fill_value=fill_value)
 
-        def floordiv2(lib, df, fill_value):
+        def floordiv2(df, fill_value, **kwargs):
             return df[["a", "c"]].floordiv(df[["b", "a"]], fill_value=fill_value)
 
         run_and_compare(floordiv1, data=self.data, fill_value=fill_value)
         run_and_compare(floordiv2, data=self.data, fill_value=fill_value)
 
     def test_floordiv_columns(self):
-        def floordiv1(lib, df):
+        def floordiv1(df, **kwargs):
             return df["a"] // df["b"]
 
-        def floordiv2(lib, df):
+        def floordiv2(df, **kwargs):
             return df[["a", "c"]] // df[["b", "a"]]
 
         run_and_compare(floordiv1, data=self.data)
diff --git a/modin/pandas/test/dataframe/test_join_sort.py b/modin/pandas/test/dataframe/test_join_sort.py
--- a/modin/pandas/test/dataframe/test_join_sort.py
+++ b/modin/pandas/test/dataframe/test_join_sort.py
@@ -37,7 +37,7 @@
     extra_test_parameters,
     default_to_pandas_ignore_string,
 )
-from modin.config import NPartitions, Engine
+from modin.config import NPartitions, Engine, StorageFormat
 from modin.test.test_utils import warns_that_defaulting_to_pandas
 
 NPartitions.put(4)
@@ -50,6 +50,9 @@
 # have too many such instances.
 pytestmark = pytest.mark.filterwarnings(default_to_pandas_ignore_string)
 
+# Initialize env for storage format detection in @pytest.mark.*
+pd.DataFrame()
+
 
 @pytest.mark.parametrize("data", test_data_values, ids=test_data_keys)
 def test_combine(data):
@@ -62,6 +65,9 @@ def test_combine(data):
     )
 
 
+@pytest.mark.xfail(
+    StorageFormat.get() == "Hdk", reason="https://github.com/intel-ai/hdk/issues/264"
+)
 @pytest.mark.parametrize(
     "test_data, test_data2",
     [
@@ -526,10 +532,29 @@ def test_sort_values(
     if ascending is None and key is not None:
         pytest.skip("Pandas bug #41318")
 
+    # If index is preserved and `key` function is ``None``,
+    # it could be sorted along rows differently from pandas.
+    # The order of NA rows, sorted by HDK, is different (but still valid)
+    # from pandas. To make the index identical to pandas, we add the
+    # index names to 'by'.
+    by_index_names = None
+    if (
+        StorageFormat.get() == "Hdk"
+        and not ignore_index
+        and key is None
+        and (axis == 0 or axis == "rows")
+    ):
+        by_index_names = []
     if "multiindex" in by:
         index = generate_multiindex(len(data[list(data.keys())[0]]), nlevels=2)
         columns = generate_multiindex(len(data.keys()), nlevels=2)
         data = {columns[ind]: data[key] for ind, key in enumerate(data)}
+        if by_index_names is not None:
+            by_index_names.extend(index.names)
+    elif by_index_names is not None:
+        index = pd.RangeIndex(0, len(next(iter(data.values()))), name="test_idx")
+        columns = None
+        by_index_names.append(index.name)
     else:
         index = None
         columns = None
@@ -553,6 +578,9 @@ def test_sort_values(
         else:
             raise Exception('Unknown "by" specifier:' + b)
 
+    if by_index_names is not None:
+        by_list.extend(by_index_names)
+
     # Create "ascending" list
     if ascending in ["list_first_True", "list_first_False"]:
         start = 0 if ascending == "list_first_False" else 1