mirror of https://github.com/apache/cassandra
354 lines
15 KiB
Java
354 lines
15 KiB
Java
/*
|
|
* 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.
|
|
*/
|
|
|
|
package org.apache.cassandra.schema;
|
|
|
|
import java.lang.reflect.InvocationTargetException;
|
|
import java.lang.reflect.Method;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.Map;
|
|
|
|
import com.google.common.collect.ImmutableMap;
|
|
|
|
import org.junit.Test;
|
|
|
|
import accord.utils.Gen;
|
|
|
|
import org.apache.cassandra.config.Config;
|
|
import org.apache.cassandra.config.InheritingClass;
|
|
import org.apache.cassandra.config.ParameterizedClass;
|
|
import org.apache.cassandra.db.memtable.SkipListMemtableFactory;
|
|
import org.apache.cassandra.exceptions.ConfigurationException;
|
|
import org.apache.cassandra.utils.ClassLoadingTestSupport;
|
|
import org.apache.cassandra.utils.ConfigGenBuilder;
|
|
|
|
import static accord.utils.Property.qt;
|
|
import static org.apache.cassandra.config.YamlConfigurationLoader.fromMap;
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
|
import static org.junit.Assert.assertEquals;
|
|
import static org.junit.Assert.assertTrue;
|
|
import static org.junit.Assert.fail;
|
|
|
|
public class MemtableParamsTest
|
|
{
|
|
static final ParameterizedClass DEFAULT = SkipListMemtableFactory.CONFIGURATION;
|
|
|
|
@Test
|
|
public void testDefault()
|
|
{
|
|
Map<String, ParameterizedClass> map = MemtableParams.expandDefinitions(ImmutableMap.of());
|
|
assertEquals(ImmutableMap.of("default", DEFAULT), map);
|
|
}
|
|
|
|
@Test
|
|
public void testInvalidFactoryMethodDoesNotInitializeClass() throws Exception
|
|
{
|
|
ClassLoadingTestSupport.assertNotInitialized(MemtableFactoryInvalidReturnType.class);
|
|
|
|
assertThatThrownBy(() -> getMemtableFactory(MemtableFactoryInvalidReturnType.class))
|
|
.isInstanceOf(ConfigurationException.class)
|
|
.hasStackTraceContaining("must return");
|
|
|
|
assertThat(ClassLoadingTestSupport.wasInitialized(MemtableFactoryInvalidReturnType.class)).isFalse();
|
|
}
|
|
|
|
@Test
|
|
public void testInvalidFactoryFieldDoesNotInitializeClass() throws Exception
|
|
{
|
|
ClassLoadingTestSupport.assertNotInitialized(MemtableFactoryInvalidFieldType.class);
|
|
|
|
assertThatThrownBy(() -> getMemtableFactory(MemtableFactoryInvalidFieldType.class))
|
|
.isInstanceOf(ConfigurationException.class)
|
|
.hasStackTraceContaining("must be of type");
|
|
|
|
assertThat(ClassLoadingTestSupport.wasInitialized(MemtableFactoryInvalidFieldType.class)).isFalse();
|
|
}
|
|
|
|
private static void getMemtableFactory(Class<?> memtableClass) throws Exception
|
|
{
|
|
Method method = MemtableParams.class.getDeclaredMethod("getMemtableFactory", ParameterizedClass.class);
|
|
method.setAccessible(true);
|
|
try
|
|
{
|
|
method.invoke(null, new ParameterizedClass(memtableClass.getName()));
|
|
}
|
|
catch (InvocationTargetException e)
|
|
{
|
|
if (e.getCause() instanceof ConfigurationException)
|
|
throw (ConfigurationException) e.getCause();
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testDefaultRemapped()
|
|
{
|
|
Map<String, ParameterizedClass> map = MemtableParams.expandDefinitions
|
|
(
|
|
ImmutableMap.of("remap", new InheritingClass("default", null, null))
|
|
);
|
|
assertEquals(ImmutableMap.of("default", DEFAULT,
|
|
"remap", DEFAULT),
|
|
map);
|
|
}
|
|
|
|
@Test
|
|
public void testOne()
|
|
{
|
|
final InheritingClass one = new InheritingClass(null, "SkipList", null);
|
|
Map<String, ParameterizedClass> map = MemtableParams.expandDefinitions(ImmutableMap.of("one", one));
|
|
assertEquals(ImmutableMap.of("default", DEFAULT,
|
|
"one", one),
|
|
map);
|
|
}
|
|
|
|
@Test
|
|
public void testOrderingDoesNotMatter()
|
|
{
|
|
// linked hash map preserves insertion order
|
|
Map<String, InheritingClass> config = new LinkedHashMap<>();
|
|
|
|
config.put("default", new InheritingClass("trie", null, null));
|
|
config.put("abc", new InheritingClass(null, "Abc", ImmutableMap.of("c", "d")));
|
|
config.put("skiplist", new InheritingClass("skiplistOnSteroids", "SkipListMemtable", ImmutableMap.of("e", "f")));
|
|
config.put("skiplistOnSteroids", new InheritingClass("abc", null, ImmutableMap.of("a", "b")));
|
|
config.put("trie", new InheritingClass(null, "TrieMemtable", null));
|
|
|
|
Map<String, ParameterizedClass> map = MemtableParams.expandDefinitions(config);
|
|
assertEquals("TrieMemtable", map.get("default").class_name);
|
|
|
|
// this inherits abc which has c as config parameter
|
|
assertTrue(map.get("skiplistOnSteroids").parameters.containsKey("a"));
|
|
assertTrue(map.get("skiplistOnSteroids").parameters.containsKey("c"));
|
|
assertEquals(map.get("skiplistOnSteroids").class_name, config.get("abc").class_name);
|
|
|
|
// this inherits from skiplistOnSteroids which so params are carried over as well
|
|
assertTrue(map.get("skiplist").parameters.containsKey("a"));
|
|
assertTrue(map.get("skiplist").parameters.containsKey("c"));
|
|
assertTrue(map.get("skiplist").parameters.containsKey("e"));
|
|
assertEquals(map.get("skiplist").class_name, "SkipListMemtable");
|
|
|
|
Map<String, InheritingClass> config2 = new LinkedHashMap<>();
|
|
config2.put("skiplist", new InheritingClass(null, "SkipListMemtable", null));
|
|
config2.put("trie", new InheritingClass(null, "TrieMemtable", null));
|
|
config2.put("default", new InheritingClass("trie", null, null));
|
|
|
|
Map<String, ParameterizedClass> map2 = MemtableParams.expandDefinitions(config2);
|
|
assertEquals("TrieMemtable", map2.get("default").class_name);
|
|
}
|
|
|
|
@Test
|
|
public void testExtends()
|
|
{
|
|
final InheritingClass one = new InheritingClass(null, "SkipList", null);
|
|
Map<String, ParameterizedClass> map = MemtableParams.expandDefinitions
|
|
(
|
|
ImmutableMap.of("one", one,
|
|
"two", new InheritingClass("one",
|
|
null,
|
|
ImmutableMap.of("extra", "value")))
|
|
);
|
|
|
|
assertEquals(ImmutableMap.of("default", DEFAULT,
|
|
"one", one,
|
|
"two", new ParameterizedClass("SkipList",
|
|
ImmutableMap.of("extra", "value"))),
|
|
map);
|
|
}
|
|
|
|
@Test
|
|
public void testExtendsReplace()
|
|
{
|
|
final InheritingClass one = new InheritingClass(null,
|
|
"SkipList",
|
|
ImmutableMap.of("extra", "valueOne"));
|
|
Map<String, ParameterizedClass> map = MemtableParams.expandDefinitions
|
|
(
|
|
ImmutableMap.of("one", one,
|
|
"two", new InheritingClass("one",
|
|
null,
|
|
ImmutableMap.of("extra", "value")))
|
|
);
|
|
assertEquals(ImmutableMap.of("default", DEFAULT,
|
|
"one", one,
|
|
"two", new ParameterizedClass("SkipList",
|
|
ImmutableMap.of("extra", "value"))),
|
|
map);
|
|
}
|
|
|
|
@Test
|
|
public void testDoubleExtends()
|
|
{
|
|
final InheritingClass one = new InheritingClass(null, "SkipList", null);
|
|
Map<String, ParameterizedClass> map = MemtableParams.expandDefinitions
|
|
(
|
|
ImmutableMap.of("one", one,
|
|
"two", new InheritingClass("one",
|
|
null,
|
|
ImmutableMap.of("param", "valueTwo",
|
|
"extra", "value")),
|
|
"three", new InheritingClass("two",
|
|
"OtherClass",
|
|
ImmutableMap.of("param", "valueThree",
|
|
"extraThree", "three")))
|
|
);
|
|
assertEquals(ImmutableMap.of("default", DEFAULT,
|
|
"one", one,
|
|
"two", new ParameterizedClass("SkipList",
|
|
ImmutableMap.of("param", "valueTwo",
|
|
"extra", "value")),
|
|
"three", new ParameterizedClass("OtherClass",
|
|
ImmutableMap.of("param", "valueThree",
|
|
"extra", "value",
|
|
"extraThree", "three"))),
|
|
map);
|
|
}
|
|
|
|
@Test
|
|
public void testInvalidSelfExtends()
|
|
{
|
|
try
|
|
{
|
|
Map<String, ParameterizedClass> map = MemtableParams.expandDefinitions
|
|
(
|
|
ImmutableMap.of("one", new InheritingClass("one",
|
|
null,
|
|
ImmutableMap.of("extra", "value")))
|
|
);
|
|
fail("Expected exception.");
|
|
}
|
|
catch (ConfigurationException e)
|
|
{
|
|
// expected
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testReplaceDefault()
|
|
{
|
|
final InheritingClass one = new InheritingClass(null,
|
|
"SkipList",
|
|
ImmutableMap.of("extra", "valueOne"));
|
|
Map<String, ParameterizedClass> map = MemtableParams.expandDefinitions(ImmutableMap.of("default", one));
|
|
assertEquals(ImmutableMap.of("default", one), map);
|
|
}
|
|
|
|
@Test
|
|
public void testDefaultExtends()
|
|
{
|
|
final InheritingClass one = new InheritingClass(null,
|
|
"SkipList",
|
|
ImmutableMap.of("extra", "valueOne"));
|
|
Map<String, ParameterizedClass> map = MemtableParams.expandDefinitions
|
|
(
|
|
ImmutableMap.of("one", one,
|
|
"default", new InheritingClass("one", null, ImmutableMap.of()))
|
|
);
|
|
assertEquals(ImmutableMap.of("one", one,
|
|
"default", one),
|
|
map);
|
|
}
|
|
// Note: The factories constructed from these parameters are tested in the CreateTest and AlterTest.
|
|
|
|
@Test
|
|
public void testExpandDefinitions()
|
|
{
|
|
Gen<Map<String, InheritingClass>> gen = new ConfigGenBuilder()
|
|
.buildMemtable()
|
|
.map(m -> fromMap(m, Config.class))
|
|
.map(c -> c.memtable.configurations);
|
|
qt().forAll(gen).check(configs -> {
|
|
Map<String, ParameterizedClass> result = MemtableParams.expandDefinitions(configs);
|
|
assertThat(result.keySet()).isEqualTo(configs.keySet());
|
|
for (Map.Entry<String, InheritingClass> e : configs.entrySet()) {
|
|
if (e.getValue().inherits == null) continue;
|
|
ParameterizedClass parent = result.get(e.getValue().inherits);
|
|
ParameterizedClass src = result.get(e.getKey());
|
|
assertThat(src.class_name).isEqualTo(parent.class_name);
|
|
assertThat(src.parameters).isEqualTo(parent.parameters);
|
|
}
|
|
});
|
|
}
|
|
|
|
@Test
|
|
public void testInheritsNonExistent()
|
|
{
|
|
try
|
|
{
|
|
Map<String, ParameterizedClass> map = MemtableParams.expandDefinitions
|
|
(
|
|
ImmutableMap.of("one", new InheritingClass("two",
|
|
null,
|
|
ImmutableMap.of("extra", "value")),
|
|
"two", new InheritingClass("three",
|
|
null,
|
|
ImmutableMap.of("extra2", "value2")))
|
|
);
|
|
fail("Expected exception.");
|
|
}
|
|
catch (ConfigurationException e)
|
|
{
|
|
// expected
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testInvalidLoops()
|
|
{
|
|
try
|
|
{
|
|
Map<String, ParameterizedClass> map = MemtableParams.expandDefinitions
|
|
(
|
|
ImmutableMap.of("one", new InheritingClass("two",
|
|
null,
|
|
ImmutableMap.of("extra", "value")),
|
|
"two", new InheritingClass("one",
|
|
null,
|
|
ImmutableMap.of("extra2", "value2")))
|
|
);
|
|
fail("Expected exception.");
|
|
}
|
|
catch (ConfigurationException e)
|
|
{
|
|
// expected
|
|
}
|
|
|
|
try
|
|
{
|
|
Map<String, ParameterizedClass> map = MemtableParams.expandDefinitions
|
|
(
|
|
ImmutableMap.of("one", new InheritingClass("two",
|
|
null,
|
|
ImmutableMap.of("extra", "value")),
|
|
"two", new InheritingClass("three",
|
|
null,
|
|
ImmutableMap.of("extra2", "value2")),
|
|
"three", new InheritingClass("one",
|
|
null,
|
|
ImmutableMap.of("extra3", "value3")))
|
|
);
|
|
fail("Expected exception.");
|
|
}
|
|
catch (ConfigurationException e)
|
|
{
|
|
// expected
|
|
}
|
|
}
|
|
}
|