Package io.crate.operation.scalar.geo

Source Code of io.crate.operation.scalar.geo.DistanceFunctionTest

/*
* Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
* license agreements.  See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.  Crate 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.
*
* However, if you have executed another commercial license agreement
* with Crate these terms will supersede the license and you may use the
* software solely pursuant to the terms of the relevant commercial agreement.
*/

package io.crate.operation.scalar.geo;

import com.google.common.collect.Lists;
import io.crate.metadata.FunctionIdent;
import io.crate.metadata.Functions;
import io.crate.operation.Input;
import io.crate.operation.scalar.ScalarFunctionModule;
import io.crate.planner.DataTypeVisitor;
import io.crate.planner.symbol.Function;
import io.crate.planner.symbol.Literal;
import io.crate.planner.symbol.Symbol;
import io.crate.types.ArrayType;
import io.crate.types.DataType;
import io.crate.types.DataTypes;
import org.elasticsearch.common.inject.Injector;
import org.elasticsearch.common.inject.ModulesBuilder;
import org.hamcrest.Matchers;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static io.crate.testing.TestingHelpers.assertLiteralSymbol;
import static io.crate.testing.TestingHelpers.createReference;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.*;

public class DistanceFunctionTest {

    private Functions functions;

    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    @Before
    public void setUp() throws Exception {
        ModulesBuilder modules = new ModulesBuilder();
        modules.add(new ScalarFunctionModule());
        Injector injector = modules.createInjector();
        functions = injector.getInstance(Functions.class);
    }

    private DistanceFunction getFunction(List<DataType> types) {
        return (DistanceFunction)functions.get(
                new FunctionIdent(DistanceFunction.NAME, types));
    }

    private DistanceFunction functionFromArgs(List<? extends Symbol> args) {
        List<DataType> dataTypes = new ArrayList<>(args.size());
        for (Symbol arg : args) {
            dataTypes.add(DataTypeVisitor.fromSymbol(arg));
        }
        return getFunction(dataTypes);
    }

    @SuppressWarnings("unchecked")
    private Double evaluate(List<Literal> args) {
        return functionFromArgs(args).evaluate(args.toArray(new Input[args.size()]));
    }

    @SuppressWarnings("unchecked")
    private Symbol normalize(List<? extends Symbol> args) {
        DistanceFunction distanceFunction = functionFromArgs(args);
        return distanceFunction.normalizeSymbol(new Function(distanceFunction.info(), (List<Symbol>)args));
    }

    @Test
    public void testResolveWithTooManyArguments() throws Exception {
        expectedException.expect(IllegalArgumentException.class);
        expectedException.expectMessage("distance takes 2 arguments, not 4");
        functions.get(new FunctionIdent(DistanceFunction.NAME,
                Arrays.<DataType>asList(DataTypes.STRING, DataTypes.STRING, DataTypes.STRING, DataTypes.STRING)));
    }

    @Test
    public void testResolveWithInvalidType() throws Exception {
        expectedException.expect(IllegalArgumentException.class);
        expectedException.expectMessage("distance can't handle arguments of type \"long\"");
        functions.get(new FunctionIdent(DistanceFunction.NAME,
                Arrays.<DataType>asList(DataTypes.LONG, DataTypes.GEO_POINT)));
    }

    @Test
    public void testEvaluateWithTwoGeoPointLiterals() throws Exception {
        Double distance = evaluate(Arrays.<Literal>asList(
                Literal.newLiteral(DataTypes.GEO_POINT, new Double[]{10.04, 28.02}),
                Literal.newLiteral(DataTypes.GEO_POINT, DataTypes.GEO_POINT.value("POINT(10.30 29.3)"))));
        assertThat(distance, is(144623.6842773458));
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testNormalizeWithStringTypes() throws Exception {
        Symbol symbol = normalize(Arrays.<Symbol>asList(
                Literal.newLiteral("POINT (10 20)"),
                Literal.newLiteral("POINT (11 21)")
        ));
        assertLiteralSymbol(symbol, 152462.70754934277);
    }

    @Test
    public void testNormalizeWithDoubleArray() throws Exception {
        DataType type = new ArrayType(DataTypes.DOUBLE);
        Symbol symbol = normalize(Arrays.<Symbol>asList(
                Literal.newLiteral(type, new Double[]{10.0, 20.0}),
                Literal.newLiteral(type, new Double[]{11.0, 21.0})
        ));
        assertLiteralSymbol(symbol, 152462.70754934277);
    }

    @Test
    @SuppressWarnings("unchecked")
    public void testNormalizeWithInvalidReferences() throws Exception {
        expectedException.expect(IllegalArgumentException.class);
        expectedException.expectMessage("Cannot convert \"dummyTable.foo\" to a geo point");

        normalize(Arrays.<Symbol>asList(
                createReference("foo", DataTypes.STRING),
                Literal.newLiteral(DataTypes.GEO_POINT, new Double[]{10.04, 28.02})
        ));
    }

    @Test
    public void testNormalizeWithValidRefAndStringLiteral() throws Exception {
        Function symbol = (Function) normalize(Arrays.<Symbol>asList(
                createReference("foo", DataTypes.GEO_POINT),
                Literal.newLiteral("POINT(10 20)")
        ));
        assertLiteralSymbol(symbol.arguments().get(1),
                new Double[]{10.0d, 20.0d}, DataTypes.GEO_POINT);

        // args reversed
        symbol = (Function) normalize(Arrays.<Symbol>asList(
                Literal.newLiteral("POINT(10 20)"),
                createReference("foo", DataTypes.GEO_POINT)
        ));
        assertLiteralSymbol(symbol.arguments().get(1),
                new Double[] { 10.0d, 20.0d }, DataTypes.GEO_POINT);
    }

    @Test
    public void testNormalizeWithValidRefAndGeoPointLiteral() throws Exception {
        Function symbol = (Function) normalize(Arrays.<Symbol>asList(
                createReference("foo", DataTypes.GEO_POINT),
                Literal.newLiteral(DataTypes.GEO_POINT, DataTypes.GEO_POINT.value("POINT (10 20)"))
        ));
        assertLiteralSymbol(symbol.arguments().get(1),
                new Double[]{10.0d, 20.0d}, DataTypes.GEO_POINT);

        // args reversed
        symbol = (Function) normalize(Arrays.<Symbol>asList(
                Literal.newLiteral(DataTypes.GEO_POINT, DataTypes.GEO_POINT.value("POINT (10 20)")),
                createReference("foo", DataTypes.GEO_POINT)
        ));
        assertLiteralSymbol(symbol.arguments().get(1),
                new Double[] { 10.0d, 20.0d }, DataTypes.GEO_POINT);
    }

    @Test
    public void testNormalizeWithValidGeoPointLiterals() throws Exception {
        Literal symbol = (Literal) normalize(Arrays.<Symbol>asList(
                Literal.newLiteral(DataTypes.GEO_POINT, DataTypes.GEO_POINT.value("POINT (10 20)")),
                Literal.newLiteral(DataTypes.GEO_POINT, DataTypes.GEO_POINT.value("POINT (30 40)"))
        ));
        assertThat(symbol.value(), instanceOf(Double.class));

        // args reversed
        symbol = (Literal) normalize(Arrays.<Symbol>asList(
                Literal.newLiteral(DataTypes.GEO_POINT, DataTypes.GEO_POINT.value("POINT (30 40)")),
                Literal.newLiteral(DataTypes.GEO_POINT, DataTypes.GEO_POINT.value("POINT (10 20)"))
        ));
        assertThat(symbol.value(), instanceOf(Double.class));
    }

    @Test
    public void testNormalizeWithTwoValidRefs() throws Exception {
        List<Symbol> args = Arrays.<Symbol>asList(
                createReference("foo", DataTypes.GEO_POINT),
                createReference("foo2", DataTypes.GEO_POINT));
        DistanceFunction distanceFunction = functionFromArgs(args);
        Function functionSymbol = new Function(distanceFunction.info(), args);
        Function normalizedFunction = (Function)distanceFunction.normalizeSymbol(functionSymbol);
        assertThat(functionSymbol, Matchers.sameInstance(normalizedFunction));
    }

    @Test
    public void testWithNullValue() throws Exception {
        List<Literal> args = Arrays.<Literal>asList(
                Literal.newLiteral(DataTypes.GEO_POINT, null),
                Literal.newLiteral(DataTypes.GEO_POINT, DataTypes.GEO_POINT.value("POINT (10 20)"))
        );
        Double distance = evaluate(args);
        assertNull(distance);
        Symbol distanceSymbol = normalize(args);
        assertNull(((Literal) distanceSymbol).value());

        distanceSymbol = normalize(Lists.reverse(args));
        assertNull(((Literal) distanceSymbol).value());
    }
}
TOP

Related Classes of io.crate.operation.scalar.geo.DistanceFunctionTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.