 #include <cstdlib>
 #include <iostream>
 #include <vector>
+#include <functional>
 
 #include <thrust/device_vector.h>
 #include <thrust/sort.h>

    std::vector<int> data(dev_vec.size());
    thrust::copy(dev_vec.begin(), dev_vec.end(), data.begin());
    return data;
}

gdf_error

    ASSERT_EQ(err, GDF_SUCCESS);
}

TEST(join_TEST, gdf_inner_join) {
    std::vector<int> l{0, 0, 1, 2, 3};
    std::vector<int> r{0, 1, 2, 2, 3};
    thrust::device_vector<int> dl, dr, l_pos, r_pos;

    auto err = call_gdf_single_column_test(l, r, dl, dr, l_pos, r_pos, gdf_inner_join_generic);

    thrust::device_vector<int> l_idx(l_pos.size());
    thrust::device_vector<int> r_idx(r_pos.size());

    thrust::gather(l_pos.begin(), l_pos.end(), dl.begin(), l_idx.begin());
    thrust::gather(r_pos.begin(), r_pos.end(), dr.begin(), r_idx.begin());

    EXPECT_THAT(host_vec(l_idx), ElementsAreArray(host_vec(r_idx)));
    EXPECT_THAT(host_vec(l_pos), ElementsAre(0, 1, 2, 3, 3, 4));
    EXPECT_THAT(host_vec(r_pos), ElementsAre(0, 0, 1, 2, 3, 4));

    ASSERT_EQ(err, GDF_SUCCESS);
}

TEST(join_TEST, gdf_left_join) {
    std::vector<int> l{0, 0, 4, 5, 5};
    std::vector<int> r{0, 0, 2, 3, 5};
    thrust::device_vector<int> dl, dr, l_pos, r_pos;

    auto err = call_gdf_single_column_test(l, r, dl, dr, l_pos, r_pos, gdf_left_join_generic);

    thrust::device_vector<int> l_idx(l_pos.size());
    thrust::device_vector<int> r_idx(r_pos.size());

    thrust::gather(l_pos.begin(), l_pos.end(), dl.begin(), l_idx.begin());
    thrust::gather(r_pos.begin(), r_pos.end(), dr.begin(), r_idx.begin());

    EXPECT_THAT(host_vec(l_idx), ElementsAre(0, 0, 0, 0, 4, 5, 5));
    EXPECT_THAT(host_vec(l_pos), ElementsAre(0, 0, 1, 1, 2, 3, 4));
    EXPECT_THAT(host_vec(r_pos), ElementsAre(0, 1, 0, 1, -1, 4, 4));

    ASSERT_EQ(err, GDF_SUCCESS);
}
