// This file is part of OpenTSDB.
// Copyright (C) 2015 The OpenTSDB Authors.
//
// This program is free software: you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 2.1 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 Lesser
// General Public License for more details. You should have received a copy
// of the GNU Lesser General Public License along with this program. If not,
// see <http://www.gnu.org/licenses/>.
package net.opentsdb.core;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
import net.opentsdb.uid.NoSuchUniqueId;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
public class TestRowKey extends BaseTsdbTest {
@Test
public void metricNameAsync() throws Exception {
final byte[] key = { 0, 0, 1, 0x50, (byte) 0xE2, 0x27, 0, 0, 0, 1, 0, 0, 1};
assertEquals(METRIC_STRING, RowKey.metricNameAsync(tsdb, key)
.joinUninterruptibly());
}
@Test
public void metricNameAsyncSalted() throws Exception {
PowerMockito.mockStatic(Const.class);
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(1);
byte[] key = { 0, 0, 0, 1, 0x50, (byte) 0xE2, 0x27, 0, 0, 0, 1, 0, 0, 1};
assertEquals(METRIC_STRING, RowKey.metricNameAsync(tsdb, key)
.joinUninterruptibly());
key = new byte[] { 1, 0, 0, 1, 0x50, (byte) 0xE2, 0x27, 0, 0, 0, 1, 0, 0, 1};
assertEquals(METRIC_STRING, RowKey.metricNameAsync(tsdb, key)
.joinUninterruptibly());
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(2);
key = new byte[] { 0, 0, 0, 0, 1, 0x50, (byte) 0xE2, 0x27, 0, 0, 0, 1, 0, 0, 1};
assertEquals(METRIC_STRING, RowKey.metricNameAsync(tsdb, key)
.joinUninterruptibly());
key = new byte[] { 0, 1, 0, 0, 1, 0x50, (byte) 0xE2, 0x27, 0, 0, 0, 1, 0, 0, 1};
assertEquals(METRIC_STRING, RowKey.metricNameAsync(tsdb, key)
.joinUninterruptibly());
}
@Test (expected = IllegalArgumentException.class)
public void metricNameAsyncRowNull() throws Exception {
RowKey.metricNameAsync(tsdb, null).joinUninterruptibly();
}
@Test (expected = IllegalArgumentException.class)
public void metricNameAsyncRowEmpty() throws Exception {
RowKey.metricNameAsync(tsdb, new byte[] { }).joinUninterruptibly();
}
@Test (expected = IllegalArgumentException.class)
public void metricNameAsyncRowTooShort() throws Exception {
RowKey.metricNameAsync(tsdb, new byte[] { 0, 1 }).joinUninterruptibly();
}
@Test (expected = IllegalArgumentException.class)
public void metricNameAsyncMissingSalt() throws Exception {
PowerMockito.mockStatic(Const.class);
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(1);
RowKey.metricNameAsync(tsdb, new byte[] { 0, 0, 1 }).joinUninterruptibly();
}
@Test (expected = NoSuchUniqueId.class)
public void metricNameAsyncNoSuchUniqueId() throws Exception {
final byte[] key = { 0, 0, 3, 0x50, (byte) 0xE2, 0x27, 0, 0, 0, 1, 0, 0, 1};
RowKey.metricNameAsync(tsdb, key).joinUninterruptibly();
}
@Test (expected = NullPointerException.class)
public void metricNameAsyncNullTsdb() throws Exception {
final byte[] key = { 0, 0, 1, 0x50, (byte) 0xE2, 0x27, 0, 0, 0, 1, 0, 0, 1};
RowKey.metricNameAsync(null, key).joinUninterruptibly();
}
@Test
public void rowKeyFromTSUID() throws Exception {
final byte[] tsuid = { 0, 0, 1, 0, 0, 1, 0, 0, 2 };
byte[] key = { 0, 0, 1, 0x50, (byte) 0xE2, 0x27, 0, 0, 0, 1, 0, 0, 2 };
assertArrayEquals(key, RowKey.rowKeyFromTSUID(tsdb, tsuid, 1356998400));
// zero timestamp
key = new byte[] { 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2 };
assertArrayEquals(key, RowKey.rowKeyFromTSUID(tsdb, tsuid, 0));
// negative timestamp; honey badger don't care
key = new byte[] { 0, 0, 1, -1, -21, 88, -128, 0, 0, 1, 0, 0, 2 };
assertArrayEquals(key, RowKey.rowKeyFromTSUID(tsdb, tsuid, -1356998400));
}
@Test (expected = NullPointerException.class)
public void rowKeyFromTSUIDNullTsuid() throws Exception {
RowKey.rowKeyFromTSUID(tsdb, null, 1356998400);
}
@Test (expected = NullPointerException.class)
public void rowKeyFromTSUIDNullTsdb() throws Exception {
final byte[] tsuid = { 0, 0, 1, 0, 0, 1, 0, 0, 2 };
RowKey.rowKeyFromTSUID(null, tsuid, 1356998400);
}
@Test (expected = IllegalArgumentException.class)
public void rowKeyFromTSUIDShortTsuid() throws Exception {
final byte[] tsuid = { 0, 1 };
RowKey.rowKeyFromTSUID(tsdb, tsuid, 1356998400);
}
@Test (expected = IllegalArgumentException.class)
public void rowKeyFromTSUIDEmptyTsuid() throws Exception {
final byte[] tsuid = { };
RowKey.rowKeyFromTSUID(tsdb, tsuid, 1356998400);
}
@Test
public void rowKeyFromTSUIDNoTags() throws Exception {
final byte[] tsuid = { 0, 0, 1 };
byte[] key = { 0, 0, 1, 0x50, (byte) 0xE2, 0x27, 0 };
assertArrayEquals(key, RowKey.rowKeyFromTSUID(tsdb, tsuid, 1356998400));
}
@Test
public void rowKeyFromTSUIDMillis() throws Exception {
final byte[] tsuid = { 0, 0, 1, 0, 0, 1, 0, 0, 2 };
byte[] key = { 0, 0, 1, 0x50, (byte) 0xE2, 0x27, 0, 0, 0, 1, 0, 0, 2 };
assertArrayEquals(key, RowKey.rowKeyFromTSUID(tsdb, tsuid, 1356998400123L));
}
@Test
public void rowKeyFromTSUIDSalted() throws Exception {
PowerMockito.mockStatic(Const.class);
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(1);
PowerMockito.when(Const.SALT_BUCKETS()).thenReturn(2);
final byte[] tsuid = { 0, 0, 1, 0, 0, 1, 0, 0, 2 };
byte[] key = { 1, 0, 0, 1, 0x50, (byte) 0xE2, 0x27, 0, 0, 0, 1, 0, 0, 2 };
assertArrayEquals(key, RowKey.rowKeyFromTSUID(tsdb, tsuid, 1356998400));
// zero timestamp
key = new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2 };
assertArrayEquals(key, RowKey.rowKeyFromTSUID(tsdb, tsuid, 0));
// negative timestamp; honey badger don't care
key = new byte[] { 1, 0, 0, 1, -1, -21, 88, -128, 0, 0, 1, 0, 0, 2 };
assertArrayEquals(key, RowKey.rowKeyFromTSUID(tsdb, tsuid, -1356998400));
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(4);
key = new byte[] { 0, 0, 0, 1, 0, 0, 1, 0x50, (byte) 0xE2, 0x27, 0,
0, 0, 1, 0, 0, 2 };
assertArrayEquals(key, RowKey.rowKeyFromTSUID(tsdb, tsuid, 1356998400));
}
@Test
public void getSalt() {
PowerMockito.mockStatic(Const.class);
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(0);
assertArrayEquals(new byte[] {}, RowKey.getSaltBytes(2));
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(1);
assertArrayEquals(new byte[] { 2 }, RowKey.getSaltBytes(2));
assertArrayEquals(new byte[] { 20 }, RowKey.getSaltBytes(20));
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(2);
assertArrayEquals(new byte[] { 0, 20 }, RowKey.getSaltBytes(20));
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(4);
assertArrayEquals(new byte[] { 0, 0, 0, 20 }, RowKey.getSaltBytes(20));
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(1);
assertArrayEquals(new byte[] { -2 }, RowKey.getSaltBytes(-2));
}
@Test (expected = NegativeArraySizeException.class)
public void getSaltNegativeWidth() {
PowerMockito.mockStatic(Const.class);
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(-1);
RowKey.getSaltBytes(2);
}
@Test
public void prefixKeyWithSaltGlobalAndNoOps() {
setupSalt();
// short rows
byte[] key = new byte[1];
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(new byte[1], key);
key = new byte[2];
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(new byte[2], key);
key = new byte[3];
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(new byte[3], key);
key = new byte[4];
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(new byte[4], key);
key = new byte[5];
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(new byte[5], key);
key = new byte[6];
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(new byte[6], key);
key = new byte[7];
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(new byte[7], key);
key = new byte[8];
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(new byte[8], key);
key = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x50, (byte) 0xE2, 0x27, 0x00};
byte[] compare = Arrays.copyOf(key, key.length);
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
key = new byte[] { 0x00, 0x00, 0x01, 0x50, (byte) 0xE2, 0x27,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
compare = Arrays.copyOf(key, key.length);
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(0);
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
}
@Test
public void prefixKeyWithSaltSameMetricDifferentTags() {
setupSalt();
byte[] key = new byte[] { 0x00, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
byte[] compare = Arrays.copyOf(key, key.length);
compare[0] = 0x08;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
key = new byte[] { 0x00, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
compare = Arrays.copyOf(key, key.length);
compare[0] = 0x10;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
key = new byte[] { 0x00, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
compare = Arrays.copyOf(key, key.length);
compare[0] = 0x00;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
key = new byte[] { 0x00, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02};
compare = Arrays.copyOf(key, key.length);
compare[0] = 0x09;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
key = new byte[] { 0x00, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01,
0x00, 0x00, 0x02, 0x00, 0x00, 0x03};
compare = Arrays.copyOf(key, key.length);
compare[0] = 0x03;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
// no tags. Shouldn't happen, but *shrug*
key = new byte[] { 0x00, 0x00, 0x00, 0x01, 0x50, (byte) 0xE2, 0x27, 0x00 };
compare = Arrays.copyOf(key, key.length);
compare[0] = 0x0C;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
}
@Test
public void prefixKeyWithSaltDifferentMetricSameTags() {
setupSalt();
byte[] key = new byte[] { 0x00, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
byte[] compare = Arrays.copyOf(key, key.length);
compare[0] = 0x08;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
key = new byte[] { 0x00, 0x00, 0x00, 0x02,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
compare = Arrays.copyOf(key, key.length);
compare[0] = 0x09;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
key = new byte[] { 0x00, 0x00, 0x00, 0x03,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
compare = Arrays.copyOf(key, key.length);
compare[0] = 0x06;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
key = new byte[] { 0x00, 0x0B, 0x14, 0x20,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
compare = Arrays.copyOf(key, key.length);
compare[0] = 0x06;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
}
@Test
public void prefixKeyWithSaltSameMetricSameTagsDifferentTimestamp() {
setupSalt();
byte[] key = new byte[] { 0x00, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
byte[] compare = Arrays.copyOf(key, key.length);
compare[0] = 0x08;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
key = new byte[] { 0x00, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x35, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
compare = Arrays.copyOf(key, key.length);
compare[0] = 0x08;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
key = new byte[] { 0x00, 0x00, 0x00, 0x01,
0x51, (byte) 0x0B, 0x13, (byte) 0x90, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
compare = Arrays.copyOf(key, key.length);
compare[0] = 0x08;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
key = new byte[] { 0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
compare = Arrays.copyOf(key, key.length);
compare[0] = 0x08;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
}
@Test
public void prefixKeyWithSaltOverwrite() {
setupSalt();
// makes sure we ignore and overwrite anything in the salt position
byte[] key = new byte[] { 0x02, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
byte[] compare = Arrays.copyOf(key, key.length);
compare[0] = 0x08;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
key = new byte[] { (byte) 0xFF, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
compare = Arrays.copyOf(key, key.length);
compare[0] = 0x08;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
key = new byte[] { (byte) 0x0E, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
compare = Arrays.copyOf(key, key.length);
compare[0] = 0x08;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
}
@Test (expected = ArithmeticException.class)
public void prefixKeyWithSaltZeroBucket() {
PowerMockito.mockStatic(Const.class);
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(1);
PowerMockito.when(Const.SALT_BUCKETS()).thenReturn(0);
final byte[] key = new byte[] { 0x02, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
RowKey.prefixKeyWithSalt(key);
}
// This actually works, but PLEASE don't do it!
@Test
public void prefixKeyWithSaltNegativeBucket() {
PowerMockito.mockStatic(Const.class);
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(1);
PowerMockito.when(Const.SALT_BUCKETS()).thenReturn(-20);
final byte[] key = new byte[] { 0x02, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
final byte[] compare = Arrays.copyOf(key, key.length);
compare[0] = 0x08;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
}
@Test
public void prefixKeyWithSaltNegativeWidth() {
PowerMockito.mockStatic(Const.class);
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(-1);
PowerMockito.when(Const.SALT_BUCKETS()).thenReturn(20);
final byte[] key = new byte[] { 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01};
final byte[] compare = Arrays.copyOf(key, key.length);
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
}
@Test
public void prefixKeyWithSaltMissingTagV() {
setupSalt();
// Honey badger don't care
final byte[] key = new byte[] { 0x02, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00, 0x00, 0x00, 0x01};
final byte[] compare = Arrays.copyOf(key, key.length);
compare[0] = 0x0D;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
}
@Test
public void prefixKeyWithSaltPartialTagK() {
setupSalt();
// Honey badger don't care
final byte[] key = new byte[] { 0x02, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27, 0x00 };
final byte[] compare = Arrays.copyOf(key, key.length);
compare[0] = 0x0C;
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(compare, key);
}
@Test (expected = ArrayIndexOutOfBoundsException.class)
public void prefixKeyWithSaltMissingTags() {
setupSalt();
final byte[] key = new byte[] { 0x02, 0x00, 0x00, 0x01,
0x50, (byte) 0xE2, 0x27 };
RowKey.prefixKeyWithSalt(key);
}
@Test (expected = NullPointerException.class)
public void prefixKeyWithSaltNullKey() {
setupSalt();
RowKey.prefixKeyWithSalt(null);
}
@Test
public void prefixKeyWithSaltEmptyKey() {
setupSalt();
final byte[] key = new byte[] {};
RowKey.prefixKeyWithSalt(key);
assertArrayEquals(new byte[] {}, key);
}
@Test
public void rowKeyContainsMetric() {
setupSalt();
final byte[] metric = new byte[] { 0, 0, 1 };
assertEquals(0, RowKey.rowKeyContainsMetric(metric,
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
// not there!
assertEquals(-1, RowKey.rowKeyContainsMetric(metric,
new byte[] { 1, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
// double salt bytes
assertEquals(-1, RowKey.rowKeyContainsMetric(metric,
new byte[] { 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
// missing salt but expecting it
assertEquals(-1, RowKey.rowKeyContainsMetric(metric,
new byte[] {0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
// both empty
assertEquals(0, RowKey.rowKeyContainsMetric(new byte[] { },
new byte[] { }));
// empty metric returns 0 TODO(clarsen) see if we really want that
assertEquals(0, RowKey.rowKeyContainsMetric(new byte[] { },
new byte[] {0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
}
@Test (expected = NullPointerException.class)
public void rowKeyContainsMetricNullMetric() {
setupSalt();
RowKey.rowKeyContainsMetric(null,
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 });
}
@Test (expected = NullPointerException.class)
public void rowKeyContainsMetricNullKey() {
setupSalt();
RowKey.rowKeyContainsMetric(new byte[] { 0, 0, 1 }, null);
}
@Test (expected = IndexOutOfBoundsException.class)
public void rowKeyContainsMetricKeyTooShortSalted() {
setupSalt();
RowKey.rowKeyContainsMetric(new byte[] { 0, 0, 1 },
new byte[] { 1, 0, 0 });
}
@Test (expected = IndexOutOfBoundsException.class)
public void rowKeyContainsMetricKeyTooShortNoSalt() {
RowKey.rowKeyContainsMetric(new byte[] { 0, 0, 1 },
new byte[] { 0, 0 });
}
@Test
public void rowKeyContainsMetricNoSalt() {
final byte[] metric = new byte[] { 0, 0, 1 };
assertEquals(0, RowKey.rowKeyContainsMetric(metric,
new byte[] { 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
// not there!
assertEquals(1, RowKey.rowKeyContainsMetric(metric,
new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
// salted but shouldn't be
assertEquals(-1, RowKey.rowKeyContainsMetric(metric,
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
}
@Test
public void saltCmp() {
setupSalt();
// diff salt, same keys
assertEquals(0, new RowKey.SaltCmp().compare(
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 },
new byte[] { 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
// same addy
final byte[] key = new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 };
assertEquals(0, new RowKey.SaltCmp().compare(key, key));
assertEquals(1, new RowKey.SaltCmp().compare(
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 4 },
new byte[] { 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
assertEquals(-1, new RowKey.SaltCmp().compare(
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 },
new byte[] { 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 4 }));
assertEquals(-1, new RowKey.SaltCmp().compare(
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0 },
new byte[] { 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
assertEquals(1, new RowKey.SaltCmp().compare(
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 },
new byte[] { 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0 }));
// nothing after the salt
assertEquals(0, new RowKey.SaltCmp().compare(
new byte[] { 1 },
new byte[] { 2 }));
// empty
assertEquals(0, new RowKey.SaltCmp().compare(
new byte[] { },
new byte[] { }));
// wider salt
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(3);
assertEquals(0, new RowKey.SaltCmp().compare(
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 },
new byte[] { 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
assertEquals(0, new RowKey.SaltCmp().compare(
new byte[] { 1, 3, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 },
new byte[] { 2, 4, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
assertEquals(0, new RowKey.SaltCmp().compare(
new byte[] { 1, 3, 5, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 },
new byte[] { 2, 4, 6, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
assertEquals(-1, new RowKey.SaltCmp().compare(
new byte[] { 1, 3, 5, 7, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 },
new byte[] { 2, 4, 6, 8, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
}
@Test (expected = NullPointerException.class)
public void saltCmpNullA() throws Exception {
setupSalt();
new RowKey.SaltCmp().compare(null,
new byte[] { 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 });
}
@Test (expected = NullPointerException.class)
public void saltCmpNullB() throws Exception {
setupSalt();
new RowKey.SaltCmp().compare(
new byte[] { 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 },
null);
}
@Test
public void saltCmpNoSalt() {
assertEquals(0, new RowKey.SaltCmp().compare(
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 },
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
// diff salt, same keys
assertEquals(-1, new RowKey.SaltCmp().compare(
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 },
new byte[] { 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
// same addy
final byte[] key = new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 };
assertEquals(0, new RowKey.SaltCmp().compare(key, key));
assertEquals(-1, new RowKey.SaltCmp().compare(
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 4 },
new byte[] { 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
assertEquals(-1, new RowKey.SaltCmp().compare(
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 },
new byte[] { 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 4 }));
assertEquals(-1, new RowKey.SaltCmp().compare(
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0 },
new byte[] { 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 }));
assertEquals(-1, new RowKey.SaltCmp().compare(
new byte[] { 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 3 },
new byte[] { 2, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0 }));
// nothing after the salt
assertEquals(-1, new RowKey.SaltCmp().compare(
new byte[] { 1 },
new byte[] { 2 }));
// empty
assertEquals(0, new RowKey.SaltCmp().compare(
new byte[] { },
new byte[] { }));
}
/**
* Mocks out the static Const class for a single salt byte with 20 buckets
*/
private static void setupSalt() {
PowerMockito.mockStatic(Const.class);
PowerMockito.when(Const.SALT_WIDTH()).thenReturn(1);
PowerMockito.when(Const.SALT_BUCKETS()).thenReturn(20);
}
}