blob: 9c614247f4648172d0265d5b56d8f729a7157aaa [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.
*/
package org.apache.druid.indexer.partitions;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
import org.apache.druid.jackson.DefaultObjectMapper;
import org.apache.druid.java.util.common.StringUtils;
import org.apache.druid.timeline.partition.HashPartitionFunction;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Test;
import java.util.Collections;
import java.util.List;
import java.util.Map;
public class HashedPartitionsSpecTest
{
private static final ObjectMapper JSON_MAPPER = new DefaultObjectMapper();
@Test
public void testDefaultValues()
{
final HashedPartitionsSpec defaultSpec = HashedPartitionsSpec.defaultSpec();
Assert.assertEquals(Collections.emptyList(), defaultSpec.getPartitionDimensions());
Assert.assertEquals(HashPartitionFunction.MURMUR3_32_ABS, defaultSpec.getPartitionFunction());
Assert.assertNull(defaultSpec.getNumShards());
Assert.assertEquals(PartitionsSpec.DEFAULT_MAX_ROWS_PER_SEGMENT, defaultSpec.getMaxRowsPerSegment().intValue());
}
@Test
public void havingTargetRowsPerSegmentOnly()
{
final HashedPartitionsSpec hadoopHashedPartitionsSpec = jsonReadWriteRead(
"{"
+ " \"targetRowsPerSegment\":100,"
+ " \"type\":\"hashed\""
+ "}"
);
Assert.assertTrue("isDeterminingPartitions", hadoopHashedPartitionsSpec.needsDeterminePartitions(true));
Assert.assertNotNull(hadoopHashedPartitionsSpec.getMaxRowsPerSegment());
Assert.assertEquals(
"getMaxRowsPerSegment",
100,
hadoopHashedPartitionsSpec.getMaxRowsPerSegment().intValue()
);
Assert.assertNull(hadoopHashedPartitionsSpec.getNumShards());
Assert.assertEquals(
"getPartitionDimensions",
ImmutableList.of(),
hadoopHashedPartitionsSpec.getPartitionDimensions()
);
}
@Test
public void havingNumShardsOnly()
{
final HashedPartitionsSpec hadoopHashedPartitionsSpec = jsonReadWriteRead(
"{"
+ " \"type\":\"hashed\","
+ " \"numShards\":2"
+ "}"
);
Assert.assertFalse("isDeterminingPartitions", hadoopHashedPartitionsSpec.needsDeterminePartitions(true));
Assert.assertNull(
"getMaxRowsPerSegment",
hadoopHashedPartitionsSpec.getMaxRowsPerSegment()
);
Assert.assertNotNull(hadoopHashedPartitionsSpec.getNumShards());
Assert.assertEquals(
"shardCount",
2,
hadoopHashedPartitionsSpec.getNumShards().intValue()
);
Assert.assertEquals(
"getPartitionDimensions",
ImmutableList.of(),
hadoopHashedPartitionsSpec.getPartitionDimensions()
);
}
@Test
public void havingIncompatiblePropertiesIsForbidden()
{
final String targetRowsPerSegment = DimensionBasedPartitionsSpec.TARGET_ROWS_PER_SEGMENT;
final String targetPartitionSize = DimensionBasedPartitionsSpec.TARGET_PARTITION_SIZE;
final String maxRowsPerSegment = PartitionsSpec.MAX_ROWS_PER_SEGMENT;
final String numShards = HashedPartitionsSpec.NUM_SHARDS;
Multimap<String, String> incompatiblePairs = ImmutableMultimap.<String, String>builder()
.put(targetRowsPerSegment, targetPartitionSize)
.put(targetRowsPerSegment, maxRowsPerSegment)
.put(targetRowsPerSegment, numShards)
.put(targetPartitionSize, maxRowsPerSegment)
.put(targetPartitionSize, numShards)
.put(maxRowsPerSegment, numShards)
.build();
for (Map.Entry<String, String> test : incompatiblePairs.entries()) {
String first = test.getKey();
String second = test.getValue();
String reasonPrefix = first + "/" + second;
String json = "{"
+ "\"type\":\"hashed\""
+ ",\"" + first + "\":100"
+ ",\"" + second + "\":100"
+ "}";
try {
jsonReadWriteRead(json);
Assert.fail(reasonPrefix + " did not throw exception");
}
catch (RuntimeException e) {
final String expectedMessage = StringUtils.format(
"At most one of [Property{name='%s', value=100}] or [Property{name='%s', value=100}] must be present",
first,
second
);
Assert.assertThat(
reasonPrefix + " has wrong failure message",
e.getMessage(),
CoreMatchers.containsString(expectedMessage)
);
}
}
}
@Test
public void defaults()
{
final HashedPartitionsSpec spec = jsonReadWriteRead("{\"type\":\"hashed\"}");
Assert.assertNotNull(spec.getMaxRowsPerSegment());
Assert.assertEquals(PartitionsSpec.DEFAULT_MAX_ROWS_PER_SEGMENT, spec.getMaxRowsPerSegment().intValue());
Assert.assertNull(spec.getNumShards());
Assert.assertEquals(Collections.emptyList(), spec.getPartitionDimensions());
}
@Test
public void handlesHistoricalNull()
{
String json = "{"
+ "\"type\":\"hashed\""
+ ",\"targetRowsPerSegment\":" + PartitionsSpec.HISTORICAL_NULL
+ ",\"numShards\":" + PartitionsSpec.HISTORICAL_NULL
+ "}";
final HashedPartitionsSpec spec = jsonReadWriteRead(json);
Assert.assertNotNull(spec.getMaxRowsPerSegment());
Assert.assertEquals(PartitionsSpec.DEFAULT_MAX_ROWS_PER_SEGMENT, spec.getMaxRowsPerSegment().intValue());
Assert.assertNull(spec.getNumShards());
Assert.assertEquals(Collections.emptyList(), spec.getPartitionDimensions());
}
@Test
public void failsIfNotPositive()
{
List<String> properties = ImmutableList.of(
DimensionBasedPartitionsSpec.TARGET_ROWS_PER_SEGMENT,
DimensionBasedPartitionsSpec.TARGET_PARTITION_SIZE,
PartitionsSpec.MAX_ROWS_PER_SEGMENT,
HashedPartitionsSpec.NUM_SHARDS
);
for (String property : properties) {
String json = "{"
+ "\"type\":\"hashed\""
+ ",\"" + property + "\":0"
+ "}";
try {
jsonReadWriteRead(json);
Assert.fail(property + " did not throw exception");
}
catch (RuntimeException e) {
String expectedMessage = property + "[0] should be positive";
Assert.assertThat(
property + " has wrong failure message",
e.getMessage(),
CoreMatchers.containsString(expectedMessage)
);
}
}
}
@Test
public void backwardCompatibleWithTargetPartitionSize()
{
String json = "{"
+ "\"type\":\"hashed\""
+ ",\"targetPartitionSize\":100"
+ "}";
HashedPartitionsSpec hadoopHashedPartitionsSpec = jsonReadWriteRead(json);
Assert.assertNotNull(hadoopHashedPartitionsSpec.getMaxRowsPerSegment());
Assert.assertEquals(
"getMaxRowsPerSegment",
100,
hadoopHashedPartitionsSpec.getMaxRowsPerSegment().intValue()
);
}
@Test
public void backwardCompatibleWithMaxRowsPerSegment()
{
String json = "{"
+ "\"type\":\"hashed\""
+ ",\"maxRowsPerSegment\":100"
+ "}";
HashedPartitionsSpec hadoopHashedPartitionsSpec = jsonReadWriteRead(json);
Assert.assertNotNull(hadoopHashedPartitionsSpec.getMaxRowsPerSegment());
Assert.assertEquals(
"getMaxRowsPerSegment",
100,
hadoopHashedPartitionsSpec.getMaxRowsPerSegment().intValue()
);
}
private static HashedPartitionsSpec jsonReadWriteRead(String s)
{
try {
byte[] jsonBytes = JSON_MAPPER.writeValueAsBytes(JSON_MAPPER.readValue(s, PartitionsSpec.class));
PartitionsSpec partitionsSpec = JSON_MAPPER.readValue(jsonBytes, PartitionsSpec.class);
Assert.assertTrue("partitionsSpec", partitionsSpec instanceof HashedPartitionsSpec);
return (HashedPartitionsSpec) partitionsSpec;
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}