blob: 79968bea1eb69cb10f2a2cf01a5caf93108840f3 [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.accumulo.core.data;
import static org.hamcrest.CoreMatchers.hasItem;
import static org.hamcrest.CoreMatchers.hasItems;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
import org.apache.accumulo.core.data.impl.KeyExtent;
import org.apache.hadoop.io.Text;
import org.junit.Before;
import org.junit.Test;
public class KeyExtentTest {
KeyExtent nke(String t, String er, String per) {
return new KeyExtent(t, er == null ? null : new Text(er), per == null ? null : new Text(per));
}
KeyExtent ke;
TreeSet<KeyExtent> set0;
@Before
public void setup() {
set0 = new TreeSet<>();
}
@Test
public void testDecodingMetadataRow() {
Text flattenedExtent = new Text("foo;bar");
ke = new KeyExtent(flattenedExtent, (Text) null);
assertEquals(new Text("bar"), ke.getEndRow());
assertEquals("foo", ke.getTableId());
assertNull(ke.getPrevEndRow());
flattenedExtent = new Text("foo<");
ke = new KeyExtent(flattenedExtent, (Text) null);
assertNull(ke.getEndRow());
assertEquals("foo", ke.getTableId());
assertNull(ke.getPrevEndRow());
flattenedExtent = new Text("foo;bar;");
ke = new KeyExtent(flattenedExtent, (Text) null);
assertEquals(new Text("bar;"), ke.getEndRow());
assertEquals("foo", ke.getTableId());
assertNull(ke.getPrevEndRow());
}
@Test
public void testFindContainingExtents() {
assertNull(KeyExtent.findContainingExtent(nke("t", null, null), set0));
assertNull(KeyExtent.findContainingExtent(nke("t", "1", "0"), set0));
assertNull(KeyExtent.findContainingExtent(nke("t", "1", null), set0));
assertNull(KeyExtent.findContainingExtent(nke("t", null, "0"), set0));
TreeSet<KeyExtent> set1 = new TreeSet<>();
set1.add(nke("t", null, null));
assertEquals(nke("t", null, null), KeyExtent.findContainingExtent(nke("t", null, null), set1));
assertEquals(nke("t", null, null), KeyExtent.findContainingExtent(nke("t", "1", "0"), set1));
assertEquals(nke("t", null, null), KeyExtent.findContainingExtent(nke("t", "1", null), set1));
assertEquals(nke("t", null, null), KeyExtent.findContainingExtent(nke("t", null, "0"), set1));
TreeSet<KeyExtent> set2 = new TreeSet<>();
set2.add(nke("t", "g", null));
set2.add(nke("t", null, "g"));
assertNull(KeyExtent.findContainingExtent(nke("t", null, null), set2));
assertEquals(nke("t", "g", null), KeyExtent.findContainingExtent(nke("t", "c", "a"), set2));
assertEquals(nke("t", "g", null), KeyExtent.findContainingExtent(nke("t", "c", null), set2));
assertEquals(nke("t", "g", null), KeyExtent.findContainingExtent(nke("t", "g", "a"), set2));
assertEquals(nke("t", "g", null), KeyExtent.findContainingExtent(nke("t", "g", null), set2));
assertNull(KeyExtent.findContainingExtent(nke("t", "h", "a"), set2));
assertNull(KeyExtent.findContainingExtent(nke("t", "h", null), set2));
assertNull(KeyExtent.findContainingExtent(nke("t", "z", "f"), set2));
assertNull(KeyExtent.findContainingExtent(nke("t", null, "f"), set2));
assertEquals(nke("t", null, "g"), KeyExtent.findContainingExtent(nke("t", "z", "g"), set2));
assertEquals(nke("t", null, "g"), KeyExtent.findContainingExtent(nke("t", null, "g"), set2));
assertEquals(nke("t", null, "g"), KeyExtent.findContainingExtent(nke("t", "z", "h"), set2));
assertEquals(nke("t", null, "g"), KeyExtent.findContainingExtent(nke("t", null, "h"), set2));
TreeSet<KeyExtent> set3 = new TreeSet<>();
set3.add(nke("t", "g", null));
set3.add(nke("t", "s", "g"));
set3.add(nke("t", null, "s"));
assertNull(KeyExtent.findContainingExtent(nke("t", null, null), set3));
assertEquals(nke("t", "g", null), KeyExtent.findContainingExtent(nke("t", "g", null), set3));
assertEquals(nke("t", "s", "g"), KeyExtent.findContainingExtent(nke("t", "s", "g"), set3));
assertEquals(nke("t", null, "s"), KeyExtent.findContainingExtent(nke("t", null, "s"), set3));
assertNull(KeyExtent.findContainingExtent(nke("t", "t", "g"), set3));
assertNull(KeyExtent.findContainingExtent(nke("t", "t", "f"), set3));
assertNull(KeyExtent.findContainingExtent(nke("t", "s", "f"), set3));
assertEquals(nke("t", "s", "g"), KeyExtent.findContainingExtent(nke("t", "r", "h"), set3));
assertEquals(nke("t", "s", "g"), KeyExtent.findContainingExtent(nke("t", "s", "h"), set3));
assertEquals(nke("t", "s", "g"), KeyExtent.findContainingExtent(nke("t", "r", "g"), set3));
assertEquals(nke("t", null, "s"), KeyExtent.findContainingExtent(nke("t", null, "t"), set3));
assertNull(KeyExtent.findContainingExtent(nke("t", null, "r"), set3));
assertEquals(nke("t", "g", null), KeyExtent.findContainingExtent(nke("t", "f", null), set3));
assertNull(KeyExtent.findContainingExtent(nke("t", "h", null), set3));
TreeSet<KeyExtent> set4 = new TreeSet<>();
set4.add(nke("t1", "d", null));
set4.add(nke("t1", "q", "d"));
set4.add(nke("t1", null, "q"));
set4.add(nke("t2", "g", null));
set4.add(nke("t2", "s", "g"));
set4.add(nke("t2", null, "s"));
assertNull(KeyExtent.findContainingExtent(nke("t", null, null), set4));
assertNull(KeyExtent.findContainingExtent(nke("z", null, null), set4));
assertNull(KeyExtent.findContainingExtent(nke("t11", null, null), set4));
assertNull(KeyExtent.findContainingExtent(nke("t1", null, null), set4));
assertNull(KeyExtent.findContainingExtent(nke("t2", null, null), set4));
assertNull(KeyExtent.findContainingExtent(nke("t", "g", null), set4));
assertNull(KeyExtent.findContainingExtent(nke("z", "g", null), set4));
assertNull(KeyExtent.findContainingExtent(nke("t11", "g", null), set4));
assertNull(KeyExtent.findContainingExtent(nke("t1", "g", null), set4));
assertEquals(nke("t2", "g", null), KeyExtent.findContainingExtent(nke("t2", "g", null), set4));
assertEquals(nke("t2", "s", "g"), KeyExtent.findContainingExtent(nke("t2", "s", "g"), set4));
assertEquals(nke("t2", null, "s"), KeyExtent.findContainingExtent(nke("t2", null, "s"), set4));
assertEquals(nke("t1", "d", null), KeyExtent.findContainingExtent(nke("t1", "d", null), set4));
assertEquals(nke("t1", "q", "d"), KeyExtent.findContainingExtent(nke("t1", "q", "d"), set4));
assertEquals(nke("t1", null, "q"), KeyExtent.findContainingExtent(nke("t1", null, "q"), set4));
}
private static boolean overlaps(KeyExtent extent, SortedMap<KeyExtent,Object> extents) {
return !KeyExtent.findOverlapping(extent, extents).isEmpty();
}
@Test
public void testOverlaps() {
SortedMap<KeyExtent,Object> set0 = new TreeMap<>();
set0.put(nke("a", null, null), null);
// Nothing overlaps with the empty set
assertFalse(overlaps(nke("t", null, null), null));
assertFalse(overlaps(nke("t", null, null), set0));
SortedMap<KeyExtent,Object> set1 = new TreeMap<>();
// Everything overlaps with the infinite range
set1.put(nke("t", null, null), null);
assertTrue(overlaps(nke("t", null, null), set1));
assertTrue(overlaps(nke("t", "b", "a"), set1));
assertTrue(overlaps(nke("t", null, "a"), set1));
set1.put(nke("t", "b", "a"), null);
assertTrue(overlaps(nke("t", null, null), set1));
assertTrue(overlaps(nke("t", "b", "a"), set1));
assertTrue(overlaps(nke("t", null, "a"), set1));
// simple overlaps
SortedMap<KeyExtent,Object> set2 = new TreeMap<>();
set2.put(nke("a", null, null), null);
set2.put(nke("t", "m", "j"), null);
set2.put(nke("z", null, null), null);
assertTrue(overlaps(nke("t", null, null), set2));
assertTrue(overlaps(nke("t", "m", "j"), set2));
assertTrue(overlaps(nke("t", "z", "a"), set2));
assertFalse(overlaps(nke("t", "j", "a"), set2));
assertFalse(overlaps(nke("t", "z", "m"), set2));
// non-overlaps
assertFalse(overlaps(nke("t", "b", "a"), set2));
assertFalse(overlaps(nke("t", "z", "y"), set2));
assertFalse(overlaps(nke("t", "b", null), set2));
assertFalse(overlaps(nke("t", null, "y"), set2));
assertFalse(overlaps(nke("t", "j", null), set2));
assertFalse(overlaps(nke("t", null, "m"), set2));
// infinite overlaps
SortedMap<KeyExtent,Object> set3 = new TreeMap<>();
set3.put(nke("t", "j", null), null);
set3.put(nke("t", null, "m"), null);
assertTrue(overlaps(nke("t", "k", "a"), set3));
assertTrue(overlaps(nke("t", "k", null), set3));
assertTrue(overlaps(nke("t", "z", "k"), set3));
assertTrue(overlaps(nke("t", null, "k"), set3));
assertTrue(overlaps(nke("t", null, null), set3));
// falls between
assertFalse(overlaps(nke("t", "l", "k"), set3));
SortedMap<KeyExtent,Object> set4 = new TreeMap<>();
set4.put(nke("t", null, null), null);
assertTrue(overlaps(nke("t", "k", "a"), set4));
assertTrue(overlaps(nke("t", "k", null), set4));
assertTrue(overlaps(nke("t", "z", "k"), set4));
assertTrue(overlaps(nke("t", null, "k"), set4));
assertTrue(overlaps(nke("t", null, null), set4));
assertTrue(overlaps(nke("t", null, null), set4));
for (String er : new String[] {"z", "y", "r", null}) {
for (String per : new String[] {"a", "b", "d", null}) {
assertTrue(nke("t", "y", "b").overlaps(nke("t", er, per)));
assertTrue(nke("t", "y", null).overlaps(nke("t", er, per)));
assertTrue(nke("t", null, "b").overlaps(nke("t", er, per)));
assertTrue(nke("t", null, null).overlaps(nke("t", er, per)));
}
}
assertFalse(nke("t", "y", "b").overlaps(nke("t", "z", "y")));
assertFalse(nke("t", "y", "b").overlaps(nke("t", null, "y")));
assertFalse(nke("t", "y", null).overlaps(nke("t", "z", "y")));
assertFalse(nke("t", "y", null).overlaps(nke("t", null, "y")));
assertFalse(nke("t", "y", "b").overlaps(nke("t", "b", "a")));
assertFalse(nke("t", "y", "b").overlaps(nke("t", "b", null)));
assertFalse(nke("t", null, "b").overlaps(nke("t", "b", "a")));
assertFalse(nke("t", null, "b").overlaps(nke("t", "b", null)));
}
@Test
public void testWriteReadFields() throws Exception {
ke = nke("t", "e", "b");
assertEquals(ke, writeAndReadFields(ke));
ke = nke("t", "e", null);
assertEquals(ke, writeAndReadFields(ke));
ke = nke("t", null, "b");
assertEquals(ke, writeAndReadFields(ke));
ke = nke("t", null, null);
assertEquals(ke, writeAndReadFields(ke));
}
private KeyExtent writeAndReadFields(KeyExtent in) throws IOException {
KeyExtent out = new KeyExtent();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
in.write(new DataOutputStream(baos));
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
out.readFields(new DataInputStream(bais));
return out;
}
@SuppressWarnings("deprecation")
@Test
public void testKeyExtentsForSimpleRange() {
Collection<KeyExtent> results;
results = KeyExtent.getKeyExtentsForRange(null, null, null);
assertTrue("Non-empty set returned from no extents", results.isEmpty());
results = KeyExtent.getKeyExtentsForRange(null, null, Collections.<KeyExtent> emptySet());
assertTrue("Non-empty set returned from no extents", results.isEmpty());
KeyExtent t = nke("t", null, null);
results = KeyExtent.getKeyExtentsForRange(null, null, Collections.<KeyExtent> singleton(t));
assertEquals("Single tablet should always be returned", 1, results.size());
assertEquals(t, results.iterator().next());
}
@SuppressWarnings("deprecation")
@Test
public void testKeyExtentsForRange() {
KeyExtent b = nke("t", "b", null);
KeyExtent e = nke("t", "e", "b");
KeyExtent h = nke("t", "h", "e");
KeyExtent m = nke("t", "m", "h");
KeyExtent z = nke("t", null, "m");
set0.addAll(Arrays.asList(b, e, h, m, z));
Collection<KeyExtent> results;
results = KeyExtent.getKeyExtentsForRange(null, null, set0);
assertThat("infinite range should return full set", results.size(), is(5));
assertThat("infinite range should return full set", results, hasItems(b, e, h, m, z));
results = KeyExtent.getKeyExtentsForRange(new Text("a"), new Text("z"), set0);
assertThat("full overlap should return full set", results.size(), is(5));
assertThat("full overlap should return full set", results, hasItems(b, e, h, m, z));
results = KeyExtent.getKeyExtentsForRange(null, new Text("f"), set0);
assertThat("end row should return head set", results.size(), is(3));
assertThat("end row should return head set", results, hasItems(b, e, h));
results = KeyExtent.getKeyExtentsForRange(new Text("f"), null, set0);
assertThat("start row should return tail set", results.size(), is(3));
assertThat("start row should return tail set", results, hasItems(h, m, z));
results = KeyExtent.getKeyExtentsForRange(new Text("f"), new Text("g"), set0);
assertThat("slice should return correct subset", results.size(), is(1));
assertThat("slice should return correct subset", results, hasItem(h));
}
@Test
public void testDecodeEncode() {
assertNull(KeyExtent.decodePrevEndRow(KeyExtent.encodePrevEndRow(null)));
Text x = new Text();
assertEquals(x, KeyExtent.decodePrevEndRow(KeyExtent.encodePrevEndRow(x)));
}
}