blob: 74eba9dc109c11604ae486a9eb1f25e1c8ff0f90 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "geo/geo_functions.h"
#include <gtest/gtest.h>
#include <vector>
#include "common/logging.h"
#include "geo/geo_types.h"
#include "geo/wkt_parse.h"
#include "geo/wkt_parse_ctx.h"
#include "testutil/function_utils.h"
#include "udf/udf.h"
#include "udf/udf_internal.h"
namespace doris {
class GeoFunctionsTest : public testing::Test {
public:
GeoFunctionsTest() {}
virtual ~GeoFunctionsTest() {}
};
TEST_F(GeoFunctionsTest, st_dist_sphere) {
FunctionUtils utils;
FunctionContext* ctx = utils.get_fn_ctx();
{
DoubleVal x_lng(0.0);
DoubleVal x_lat(0.0);
DoubleVal y_lng(0.0);
DoubleVal y_lat(0.0);
auto dist = GeoFunctions::st_distance_sphere(ctx, x_lng, x_lat, y_lng, y_lat);
ASSERT_EQ(0, dist.val);
}
{
DoubleVal x_lng(0.0);
DoubleVal x_lat(0.0);
DoubleVal y_lng(0.0);
DoubleVal y_lat(1.0);
auto dist = GeoFunctions::st_distance_sphere(ctx, x_lng, x_lat, y_lng, y_lat);
LOG(INFO) << dist.val;
}
}
TEST_F(GeoFunctionsTest, st_point) {
FunctionUtils utils;
FunctionContext* ctx = utils.get_fn_ctx();
DoubleVal lng(113);
DoubleVal lat(64);
auto str = GeoFunctions::st_point(ctx, lng, lat);
ASSERT_FALSE(str.is_null);
GeoPoint point;
auto res = point.decode_from(str.ptr, str.len);
ASSERT_TRUE(res);
ASSERT_EQ(113, point.x());
ASSERT_EQ(64, point.y());
}
TEST_F(GeoFunctionsTest, st_x_y) {
FunctionUtils utils;
FunctionContext* ctx = utils.get_fn_ctx();
GeoPoint point;
point.from_coord(134, 63);
std::string buf;
point.encode_to(&buf);
auto x = GeoFunctions::st_x(ctx, StringVal((uint8_t*)buf.data(), buf.size()));
auto y = GeoFunctions::st_y(ctx, StringVal((uint8_t*)buf.data(), buf.size()));
ASSERT_EQ(134, x.val);
ASSERT_EQ(63, y.val);
}
TEST_F(GeoFunctionsTest, as_wkt) {
FunctionUtils utils;
FunctionContext* ctx = utils.get_fn_ctx();
GeoPoint point;
point.from_coord(134, 63);
std::string buf;
point.encode_to(&buf);
auto wkt = GeoFunctions::st_as_wkt(ctx, StringVal((uint8_t*)buf.data(), buf.size()));
ASSERT_STREQ("POINT (134 63)", std::string((char*)wkt.ptr, wkt.len).c_str());
}
TEST_F(GeoFunctionsTest, st_from_wkt) {
FunctionUtils utils;
FunctionContext* ctx = utils.get_fn_ctx();
GeoFunctions::st_from_wkt_prepare(ctx, FunctionContext::FRAGMENT_LOCAL);
ASSERT_EQ(nullptr, ctx->get_function_state(FunctionContext::FRAGMENT_LOCAL));
std::string wkt = "POINT (10.1 20.2)";
auto str = GeoFunctions::st_from_wkt(ctx, StringVal((uint8_t*)wkt.data(), wkt.size()));
ASSERT_FALSE(str.is_null);
GeoFunctions::st_from_wkt_close(ctx, FunctionContext::FRAGMENT_LOCAL);
// second time
{
StringVal wkt_val((uint8_t*)wkt.data(), wkt.size());
// push const value
std::vector<doris_udf::AnyVal*> const_vals;
const_vals.push_back(&wkt_val);
ctx->impl()->set_constant_args(const_vals);
// prepare
GeoFunctions::st_from_wkt_prepare(ctx, FunctionContext::FRAGMENT_LOCAL);
ASSERT_NE(nullptr, ctx->get_function_state(FunctionContext::FRAGMENT_LOCAL));
// convert
auto str2 = GeoFunctions::st_from_wkt(ctx, StringVal((uint8_t*)wkt.data(), wkt.size()));
ASSERT_FALSE(str2.is_null);
// close
GeoPoint point;
auto res = point.decode_from(str2.ptr, str2.len);
ASSERT_TRUE(res);
ASSERT_DOUBLE_EQ(10.1, point.x());
ASSERT_DOUBLE_EQ(20.2, point.y());
GeoFunctions::st_from_wkt_close(ctx, FunctionContext::FRAGMENT_LOCAL);
}
}
TEST_F(GeoFunctionsTest, st_line) {
FunctionUtils utils;
FunctionContext* ctx = utils.get_fn_ctx();
GeoFunctions::st_from_wkt_prepare(ctx, FunctionContext::FRAGMENT_LOCAL);
std::string wkt = "LINESTRING (10.1 20.2, 21.1 30.1)";
auto str = GeoFunctions::st_from_wkt(ctx, StringVal((uint8_t*)wkt.data(), wkt.size()));
ASSERT_FALSE(str.is_null);
GeoLine line;
auto res = line.decode_from(str.ptr, str.len);
ASSERT_TRUE(res);
GeoFunctions::st_from_wkt_close(ctx, FunctionContext::FRAGMENT_LOCAL);
// second time
{
StringVal wkt_val((uint8_t*)wkt.data(), wkt.size());
// push const value
std::vector<doris_udf::AnyVal*> const_vals;
const_vals.push_back(&wkt_val);
ctx->impl()->set_constant_args(const_vals);
// prepare
GeoFunctions::st_line_prepare(ctx, FunctionContext::FRAGMENT_LOCAL);
ASSERT_NE(nullptr, ctx->get_function_state(FunctionContext::FRAGMENT_LOCAL));
// convert
auto str2 = GeoFunctions::st_line(ctx, StringVal((uint8_t*)wkt.data(), wkt.size()));
ASSERT_FALSE(str2.is_null);
// close
GeoLine line;
auto res = line.decode_from(str2.ptr, str2.len);
ASSERT_TRUE(res);
GeoFunctions::st_from_wkt_close(ctx, FunctionContext::FRAGMENT_LOCAL);
}
}
TEST_F(GeoFunctionsTest, st_polygon) {
FunctionUtils utils;
FunctionContext* ctx = utils.get_fn_ctx();
GeoFunctions::st_from_wkt_prepare(ctx, FunctionContext::FRAGMENT_LOCAL);
std::string wkt = "POLYGON ((10 10, 50 10, 50 50, 10 50, 10 10))";
auto str = GeoFunctions::st_from_wkt(ctx, StringVal((uint8_t*)wkt.data(), wkt.size()));
ASSERT_FALSE(str.is_null);
// second time
{
StringVal wkt_val((uint8_t*)wkt.data(), wkt.size());
// push const value
std::vector<doris_udf::AnyVal*> const_vals;
const_vals.push_back(&wkt_val);
ctx->impl()->set_constant_args(const_vals);
// prepare
GeoFunctions::st_polygon_prepare(ctx, FunctionContext::FRAGMENT_LOCAL);
ASSERT_NE(nullptr, ctx->get_function_state(FunctionContext::FRAGMENT_LOCAL));
// convert
auto str2 = GeoFunctions::st_polygon(ctx, StringVal((uint8_t*)wkt.data(), wkt.size()));
ASSERT_FALSE(str2.is_null);
// close
GeoPolygon polygon;
auto res = polygon.decode_from(str2.ptr, str2.len);
ASSERT_TRUE(res);
GeoFunctions::st_from_wkt_close(ctx, FunctionContext::FRAGMENT_LOCAL);
}
}
TEST_F(GeoFunctionsTest, st_circle) {
FunctionUtils utils;
FunctionContext* ctx = utils.get_fn_ctx();
GeoFunctions::st_from_wkt_prepare(ctx, FunctionContext::FRAGMENT_LOCAL);
DoubleVal lng(111);
DoubleVal lat(64);
DoubleVal radius_meter(10 * 100);
auto str = GeoFunctions::st_circle(ctx, lng, lat, radius_meter);
ASSERT_FALSE(str.is_null);
// second time
{
// push const value
std::vector<doris_udf::AnyVal*> const_vals;
const_vals.push_back(&lng);
const_vals.push_back(&lat);
const_vals.push_back(&radius_meter);
ctx->impl()->set_constant_args(const_vals);
// prepare
GeoFunctions::st_circle_prepare(ctx, FunctionContext::FRAGMENT_LOCAL);
ASSERT_NE(nullptr, ctx->get_function_state(FunctionContext::FRAGMENT_LOCAL));
// convert
auto str2 = GeoFunctions::st_circle(ctx, lng, lat, radius_meter);
ASSERT_FALSE(str2.is_null);
// close
GeoCircle circle;
auto res = circle.decode_from(str2.ptr, str2.len);
ASSERT_TRUE(res);
GeoFunctions::st_from_wkt_close(ctx, FunctionContext::FRAGMENT_LOCAL);
}
}
TEST_F(GeoFunctionsTest, st_poly_line_fail) {
FunctionUtils utils;
FunctionContext* ctx = utils.get_fn_ctx();
{
GeoFunctions::st_polygon_prepare(ctx, FunctionContext::FRAGMENT_LOCAL);
std::string wkt = "POINT (10.1 20.2)";
auto str = GeoFunctions::st_polygon(ctx, StringVal((uint8_t*)wkt.data(), wkt.size()));
ASSERT_TRUE(str.is_null);
GeoFunctions::st_from_wkt_close(ctx, FunctionContext::FRAGMENT_LOCAL);
}
{
GeoFunctions::st_line_prepare(ctx, FunctionContext::FRAGMENT_LOCAL);
std::string wkt = "POINT (10.1 20.2)";
auto str = GeoFunctions::st_line(ctx, StringVal((uint8_t*)wkt.data(), wkt.size()));
ASSERT_TRUE(str.is_null);
GeoFunctions::st_from_wkt_close(ctx, FunctionContext::FRAGMENT_LOCAL);
}
}
TEST_F(GeoFunctionsTest, st_contains) {
FunctionUtils utils;
FunctionContext* ctx = utils.get_fn_ctx();
ASSERT_EQ(nullptr, ctx->get_function_state(FunctionContext::FRAGMENT_LOCAL));
std::string polygon_wkt = "POLYGON ((10 10, 50 10, 50 50, 10 50, 10 10))";
auto polygon = GeoFunctions::st_from_wkt(
ctx, StringVal((uint8_t*)polygon_wkt.data(), polygon_wkt.size()));
ASSERT_EQ(nullptr, ctx->get_function_state(FunctionContext::FRAGMENT_LOCAL));
std::string point_wkt = "POINT (25 25)";
auto point =
GeoFunctions::st_from_wkt(ctx, StringVal((uint8_t*)point_wkt.data(), point_wkt.size()));
ASSERT_EQ(nullptr, ctx->get_function_state(FunctionContext::FRAGMENT_LOCAL));
GeoFunctions::st_contains_prepare(ctx, FunctionContext::FRAGMENT_LOCAL);
ASSERT_EQ(nullptr, ctx->get_function_state(FunctionContext::FRAGMENT_LOCAL));
auto res = GeoFunctions::st_contains(ctx, polygon, point);
ASSERT_TRUE(res.val);
GeoFunctions::st_contains_close(ctx, FunctionContext::FRAGMENT_LOCAL);
}
TEST_F(GeoFunctionsTest, st_contains_cached) {
FunctionUtils utils;
FunctionContext* ctx = utils.get_fn_ctx();
GeoFunctions::st_from_wkt_prepare(ctx, FunctionContext::FRAGMENT_LOCAL);
std::string polygon_wkt = "POLYGON ((10 10, 50 10, 50 50, 10 50, 10 10))";
auto polygon = GeoFunctions::st_from_wkt(
ctx, StringVal((uint8_t*)polygon_wkt.data(), polygon_wkt.size()));
std::string point_wkt = "POINT (25 25)";
auto point =
GeoFunctions::st_from_wkt(ctx, StringVal((uint8_t*)point_wkt.data(), point_wkt.size()));
// push const value
std::vector<doris_udf::AnyVal*> const_vals;
const_vals.push_back(&polygon);
const_vals.push_back(&point);
ctx->impl()->set_constant_args(const_vals);
// prepare
GeoFunctions::st_contains_prepare(ctx, FunctionContext::FRAGMENT_LOCAL);
ASSERT_NE(nullptr, ctx->get_function_state(FunctionContext::FRAGMENT_LOCAL));
auto res = GeoFunctions::st_contains(ctx, polygon, point);
ASSERT_TRUE(res.val);
GeoFunctions::st_contains_close(ctx, FunctionContext::FRAGMENT_LOCAL);
}
} // namespace doris
int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
FLAGS_s2debug = false;
return RUN_ALL_TESTS();
}