/** * 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.server.types.*; import com.foundationdb.server.types.TypesTestClass; 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.collect.ObjectArrays; import com.google.common.collect.Sets; import com.google.common.primitives.Ints; import org.junit.After; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public final class ScalarsRegistryTest { @Test public void singleOverload() { TInputSet a = test.createOverloadWithPriority(1); test.expectInputSets(a); test.run(); } @Test public void twoOverloadsSamePriority() { TInputSet a = test.createOverloadWithPriority(1); TInputSet b = test.createOverloadWithPriority(1); test.expectInputSets(a, b); test.run(); } @Test public void twoOverloadsSparsePriorities() { TInputSet a = test.createOverloadWithPriority(-9812374); TInputSet b = test.createOverloadWithPriority(1928734); test.expectInputSets(a); test.expectInputSets(b); test.run(); } @Test public void overloadHasMultiplePriorities() { TInputSet a = test.createOverloadWithPriority(1, 2); TInputSet b = test.createOverloadWithPriority(1); TInputSet c = test.createOverloadWithPriority(2); test.expectInputSets(a, b); test.expectInputSets(a, c); test.run(); } @Test public void noOverloads() { TypesRegistryServiceImpl registry = new TypesRegistryServiceImpl(); registry.start(new InstanceFinderBuilder()); List<TPreptimeValue> args = Collections.emptyList(); assertEquals("lookup for FOO", null, registry.getScalarsResolver().getRegistry().get("foo")); test.noRunNeeded(); } @After public void checkTester() { assertTrue("Tester wasn't used", test.checked); } private final Tester test = new Tester(); private static class Tester { TInputSet createOverloadWithPriority(int priority, int... priorities) { priorities = Ints.concat(new int[] { priority }, priorities); TScalar result = new DummyScalar(FUNC_NAME, priorities); instanceFinder.put(TScalar.class, result); return onlyInputSet(result); } void expectInputSets(TInputSet priorityGroupInput, TInputSet... priorityGroupInputs) { priorityGroupInputs = ObjectArrays.concat(priorityGroupInputs, priorityGroupInput); Set<TInputSet> expectedInputs = Sets.newHashSet(priorityGroupInputs); inputSetsByPriority.add(expectedInputs); } void noRunNeeded() { assert inputSetsByPriority.isEmpty() : inputSetsByPriority; checked = true; } void run() { checked = true; TypesRegistryServiceImpl registry = new TypesRegistryServiceImpl(); registry.start(instanceFinder); Iterable<? extends ScalarsGroup<TValidatedScalar>> scalarsByPriority = registry.getScalarsResolver().getRegistry().get(FUNC_NAME); List<Set<TInputSet>> actuals = new ArrayList<>(); for (ScalarsGroup<TValidatedScalar> scalarsGroup : scalarsByPriority) { Set<TInputSet> actualInputs = new HashSet<>(); for (TScalar scalar : scalarsGroup.getOverloads()) { TInputSet overloadInput = onlyInputSet(scalar); actualInputs.add(overloadInput); } actuals.add(actualInputs); } assertEquals("input sets not equal by identity", inputSetsByPriority, actuals); } TInputSet onlyInputSet(TScalar result) { TInputSet onlyInputSet = result.inputSets().get(0); assertEquals("input sets should have size 1", Arrays.asList(onlyInputSet), result.inputSets()); return onlyInputSet; } private final InstanceFinderBuilder instanceFinder = new InstanceFinderBuilder(); private final List<Set<TInputSet>> inputSetsByPriority = new ArrayList<>(); private boolean checked = false; private static final String FUNC_NAME = "foo"; } private static class DummyScalar extends TScalarBase { @Override public List<TInputSet> inputSets() { if (inputSets == null) inputSets = super.inputSets(); return inputSets; } @Override protected void buildInputSets(TInputSetBuilder builder) { builder.covers(null, 0); } @Override protected void doEvaluate(TExecutionContext context, LazyList<? extends ValueSource> inputs, ValueTarget output) { throw new UnsupportedOperationException(); } @Override public String displayName() { return name; } @Override public TOverloadResult resultType() { return TOverloadResult.fixed(testClass); } @Override public int[] getPriorities() { return priorities; } private DummyScalar(String name, int[] priorities) { this.name = name; this.priorities = priorities; } private final String name; private final int[] priorities; private List<TInputSet> inputSets; // base class will recreate this each time, which we don't want } private static final TClass testClass = new TypesTestClass("A"); }