Package com.foundationdb.server.types.service

Source Code of com.foundationdb.server.types.service.OverloadsFolderTest

/**
* Copyright (C) 2009-2013 FoundationDB, LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package com.foundationdb.server.types.service;

import com.foundationdb.junit.NamedParameterizedRunner;
import com.foundationdb.junit.Parameterization;
import com.foundationdb.junit.ParameterizationBuilder;
import com.foundationdb.server.types.*;
import com.foundationdb.server.types.TypesTestClass;
import com.foundationdb.server.types.service.OverloadsFolder;
import com.foundationdb.server.types.service.ResolvablesRegistry;
import com.foundationdb.server.types.value.ValueSource;
import com.foundationdb.server.types.value.ValueTarget;
import com.foundationdb.server.types.texpressions.TInputSetBuilder;
import com.foundationdb.server.types.texpressions.TScalarBase;
import com.foundationdb.server.types.texpressions.TValidatedScalar;
import com.google.common.base.Function;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import static org.junit.Assert.assertEquals;

@RunWith(NamedParameterizedRunner.class)
public final class OverloadsFolderTest {

    @NamedParameterizedRunner.TestParameters
    public static Collection<Parameterization> params() {
        Cases test = new Cases();

         // "Sandwiched" overloads:
        test.overloads(
                "A, B...",
                "C, D...",
                "E, B...")
                .differentAt(0).differentAt(1).differentAt(100);
       
        // fixed arity
        test.overloads(
                "A")
                .sameAt(0).undefinedAt(1).undefinedAt(100);

        test.overloads(
                "A",
                "B")
                .differentAt(0).undefinedAt(1).undefinedAt(100);
        test.overloads(
                "A",
                "A")
                .sameAt(0).undefinedAt(1).undefinedAt(100);

        // one vararg
        test.overloads(
                "A...")
                .sameAt(0).sameAt(1).sameAt(100);

        // vararg + fixed arity
        test.overloads(
                "A",
                "B...")
                .differentAt(0).sameAt(1).sameAt(100);

        test.overloads(
                "A, B",
                "A, A...")
                .sameAt(0).differentAt(1).sameAt(2).sameAt(100);

        test.overloads(
                "A",
                "A...")
                .sameAt(0).sameAt(1).sameAt(100);

        test.overloads(
                "B...",
                "B")
                .sameAt(0).sameAt(1).sameAt(100);
       
        test.overloads(
                "A",
                "A...",
                "B...")
                .differentAt(0).differentAt(1).differentAt(100);
       
        test.overloads(
                "A...",
                "B",
                "A, B, A...")
                .differentAt(0).differentAt(1).sameAt(2).sameAt(100);

        // two varargs

        test.overloads( // note: this isn't allowed by other types components, but let's check it anyway
                "A...",
                "A...")
                .sameAt(0).sameAt(1).sameAt(100);

        test.overloads(
                "A...",
                "B...")
                .differentAt(0).differentAt(1).differentAt(100);

        test.overloads(
                "A...",
                "B, B...")
                .differentAt(0).differentAt(1).differentAt(100);
        test.overloads(
                "A...",
                "A, A...")
                .sameAt(0).sameAt(1).sameAt(100);

        test.overloads(
                "A, B, A",
                "A...")
                .sameAt(0).differentAt(1).sameAt(2).sameAt(100);
        test.overloads(
                "A, B, A...",
                "A...")
                .sameAt(0).differentAt(1).sameAt(2).sameAt(100);
        test.overloads(
                "A, B, C...",
                "A...")
                .sameAt(0).differentAt(1).differentAt(2).differentAt(100);
       
        // four overloads
        test.overloads(
                "A, B",
                "B...",
                "C, B, D",
                "E")
                .differentAt(0).sameAt(1).differentAt(2).sameAt(3).sameAt(100);

        // overloads take ANY
        test.overloads(
                "?",
                "?")
                .sameAt(0).undefinedAt(1);
        test.overloads(
                "A",
                "?")
                .sameAt(0).undefinedAt(1);
        test.overloads(
                "?",
                "A")
                .sameAt(0).undefinedAt(1);
        test.overloads(
                "?...")
                .sameAt(0).sameAt(1).sameAt(100);

        return test.build();
    }

    @Test
    public void sameTypeAt() {
        assertEquals(sameTypeAtExpected, foldResult.at(pos, null));
    }

    public OverloadsFolderTest(OverloadsFolder.Result<Boolean> foldResult, int pos, Boolean sameTypeAtExpected) {
        this.foldResult = foldResult;
        this.pos = pos;
        this.sameTypeAtExpected = sameTypeAtExpected;
    }

    private final OverloadsFolder.Result<Boolean> foldResult;
    private final int pos;
    private final Boolean sameTypeAtExpected;

    private static final Function<TClass, Boolean> notNull = new Function<TClass, Boolean>() {
        @Override
        public Boolean apply(TClass input) {
            return input != ResolvablesRegistry.differentTargetTypes;
        }
    };

    private static class Cases {
        public Cases overloads(String... overloads) {
            flush();
            this.overloadDefs = overloads;
            this.expectations = new HashMap<>();
            return this;
        }

        public Cases sameAt(int pos) {
            expectations.put(pos, Boolean.TRUE);
            return this;
        }

        public Cases differentAt(int pos) {
            expectations.put(pos, Boolean.FALSE);
            return this;
        }

        public Cases undefinedAt(int pos) {
            expectations.put(pos, null);
            return this;
        }

        public Collection<Parameterization> build() {
            flush();
            return pb.asList();
        }

        private void flush() {
            if (overloadDefs == null) {
                assert expectations == null : expectations;
                return; // must have been the first call to start()
            }
            Collection<TValidatedScalar> overloads = new ArrayList<>();
            for (String overloadDef : overloadDefs) {
                TScalar scalar = parse(overloadDef);
                TValidatedScalar validated = new TValidatedScalar(scalar);
                overloads.add(validated);
            }
            OverloadsFolder.Result<TClass> foldToClass = ResolvablesRegistry.sameInputSets.fold(overloads);
            OverloadsFolder.Result<Boolean> foldResult = foldToClass.transform(notNull);

            StringBuilder overloadsDescBuilder = new StringBuilder();
            for (int i = 0; i < overloadDefs.length; i++) {
                String overloadDef = overloadDefs[i];
                overloadsDescBuilder.append(FUNC_NAME).append('(').append(overloadDef).append(')');
                if (i + 1 < overloadDefs.length)
                    overloadsDescBuilder.append(", ");
            }
            String overloadsDescr = overloadsDescBuilder.toString();

            for (Map.Entry<Integer, Boolean> expected : expectations.entrySet()) {
                int pos = expected.getKey();
                Boolean sameTypeAt = expected.getValue();
                String caseName = overloadsDescr + " at " + pos;
                pb.add(caseName, foldResult, pos, sameTypeAt);
            }
        }

        private TScalar parse(final String overloadDef) {
            return new TScalarBase() {
                @Override
                protected void buildInputSets(TInputSetBuilder builder) {
                    String[] args = overloadDef.split(", *");
                    for (int pos = 0; pos < args.length; pos++) {
                        String arg = args[pos];
                        boolean isVararg = false;
                        if (arg.endsWith("...")) {
                            isVararg = true;
                            arg = arg.substring(0, arg.length() - 3);
                        }
                        assert arg.length() == 1 : arg;
                        char argChar = arg.charAt(0);
                        TClass tClass;
                        if (argChar == '?') {
                            tClass = null;
                        }
                        else {
                            assert Character.isLetter(argChar) : arg;
                            tClass = tClasses.get(arg);
                            if (tClass == null) {
                                tClass = new TypesTestClass(arg);
                                tClasses.put(arg, tClass);
                            }
                        }
                        if (isVararg)
                            builder.vararg(tClass);
                        else
                            builder.covers(tClass, pos);
                    }
                }

                @Override
                protected void doEvaluate(TExecutionContext context, LazyList<? extends ValueSource> inputs,
                                          ValueTarget output) {
                    throw new UnsupportedOperationException();
                }

                @Override
                public String displayName() {
                    return "FOO";
                }

                @Override
                public TOverloadResult resultType() {
                    return TOverloadResult.fixed(RET_TYPE);
                }
            };

        }

        private final ParameterizationBuilder pb = new ParameterizationBuilder();
        private final Map<String,TClass> tClasses = new HashMap<>();
        private String[] overloadDefs;
        private Map<Integer, Boolean> expectations;
    }

    private static final String FUNC_NAME = "FOO";
    private static final TClass RET_TYPE = new TypesTestClass("R");
}
TOP

Related Classes of com.foundationdb.server.types.service.OverloadsFolderTest

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.