package net.opentsdb.tools; import static org.powermock.api.mockito.PowerMockito.mock; import static org.powermock.api.mockito.PowerMockito.when; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.any; import java.util.ArrayList; import java.util.List; import net.opentsdb.core.Const; import net.opentsdb.core.RowKey; import net.opentsdb.core.TSDB; import org.hbase.async.Bytes; import org.hbase.async.GetRequest; import org.hbase.async.HBaseClient; import org.hbase.async.KeyValue; import org.hbase.async.Scanner; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.powermock.api.mockito.PowerMockito; import org.powermock.core.classloader.annotations.PowerMockIgnore; import org.powermock.core.classloader.annotations.PrepareForTest; import org.powermock.modules.junit4.PowerMockRunner; import org.powermock.reflect.Whitebox; import com.stumbleupon.async.Deferred; @RunWith(PowerMockRunner.class) @PowerMockIgnore({"javax.management.*", "javax.xml.*", "ch.qos.*", "org.slf4j.*", "com.sum.*", "org.xml.*"}) @PrepareForTest({ TSDB.class, HBaseClient.class, Scanner.class, Const.class }) public class TestCliUtils { private TSDB tsdb = null; private HBaseClient client = null; private List<byte[]> start_keys; private List<byte[]> stop_keys; @Before public void before() throws Exception { tsdb = mock(TSDB.class); client = mock(HBaseClient.class); when(tsdb.getClient()).thenReturn(client); when(tsdb.uidTable()).thenReturn("tsdb-uid".getBytes()); } @Test public void getDataTableScanners1Thread() throws Exception { setupGetDataTableScanners(256); final List<Scanner> scanners = CliUtils.getDataTableScanners(tsdb, 1); assertEquals(1, scanners.size()); assertArrayEquals(HBaseClient.EMPTY_ARRAY, start_keys.get(0)); assertArrayEquals(HBaseClient.EMPTY_ARRAY, stop_keys.get(0)); } @Test public void getDataTableScannersMultiThreaded() throws Exception { setupGetDataTableScanners(256); final List<Scanner> scanners = CliUtils.getDataTableScanners(tsdb, 15); assertEquals(15, scanners.size()); byte[] key = new byte[3]; int last_value = 0; for (int i = 0; i < 15; i++) { if (i == 0) { assertArrayEquals(HBaseClient.EMPTY_ARRAY, start_keys.get(i)); } else { assertArrayEquals(key, start_keys.get(i)); } last_value += 18; if (i == 14) { assertArrayEquals(HBaseClient.EMPTY_ARRAY, stop_keys.get(i)); } else { System.arraycopy(Bytes.fromInt(last_value), 1, key, 0, 3); assertArrayEquals(key, stop_keys.get(i)); } } } @Test public void getDataTableScannersRandom1Thread() throws Exception { setupGetDataTableScanners(0); final List<Scanner> scanners = CliUtils.getDataTableScanners(tsdb, 1); assertEquals(1, scanners.size()); assertArrayEquals(HBaseClient.EMPTY_ARRAY, start_keys.get(0)); assertArrayEquals(HBaseClient.EMPTY_ARRAY, stop_keys.get(0)); } @Test public void getDataTableScannersRandomMultiThreaded() throws Exception { setupGetDataTableScanners(0); final List<Scanner> scanners = CliUtils.getDataTableScanners(tsdb, 15); assertEquals(15, scanners.size()); byte[] key = new byte[3]; int last_value = 0; for (int i = 0; i < 15; i++) { if (i == 0) { assertArrayEquals(HBaseClient.EMPTY_ARRAY, start_keys.get(i)); } else { assertArrayEquals(key, start_keys.get(i)); } last_value += 1118481; if (i == 14) { assertArrayEquals(HBaseClient.EMPTY_ARRAY, stop_keys.get(i)); } else { System.arraycopy(Bytes.fromInt(last_value), 1, key, 0, 3); assertArrayEquals(key, stop_keys.get(i)); } } } @Test public void getDataTableScannersSalted() throws Exception { PowerMockito.mockStatic(Const.class); PowerMockito.when(Const.SALT_BUCKETS()).thenReturn(20); PowerMockito.when(Const.SALT_WIDTH()).thenReturn(1); setupGetDataTableScanners(256); final List<Scanner> scanners = CliUtils.getDataTableScanners(tsdb, 15); assertEquals(20, scanners.size()); byte[] key = new byte[1]; for (int i = 0; i < 20; i++) { if (i == 0) { assertArrayEquals(HBaseClient.EMPTY_ARRAY, start_keys.get(i)); } else { assertArrayEquals(key, start_keys.get(i)); } if (i == 19) { assertArrayEquals(HBaseClient.EMPTY_ARRAY, stop_keys.get(i)); } else { key = RowKey.getSaltBytes(i + 1); assertArrayEquals(key, stop_keys.get(i)); } } } @Test public void getDataTableScannersSaltedRandom() throws Exception { PowerMockito.mockStatic(Const.class); PowerMockito.when(Const.SALT_BUCKETS()).thenReturn(20); PowerMockito.when(Const.SALT_WIDTH()).thenReturn(1); setupGetDataTableScanners(0); final List<Scanner> scanners = CliUtils.getDataTableScanners(tsdb, 15); assertEquals(20, scanners.size()); byte[] key = new byte[1]; for (int i = 0; i < 20; i++) { if (i == 0) { assertArrayEquals(HBaseClient.EMPTY_ARRAY, start_keys.get(i)); } else { assertArrayEquals(key, start_keys.get(i)); } if (i == 19) { assertArrayEquals(HBaseClient.EMPTY_ARRAY, stop_keys.get(i)); } else { key = RowKey.getSaltBytes(i + 1); assertArrayEquals(key, stop_keys.get(i)); } } } private void setupGetDataTableScanners(final long max) { final KeyValue kv = new KeyValue(new byte[] {}, TSDB.FAMILY(), "metrics".getBytes(), Bytes.fromLong(max)); final ArrayList<KeyValue> kvs = new ArrayList<KeyValue>(1); kvs.add(kv); when(client.get(any(GetRequest.class))) .thenReturn(Deferred.<ArrayList<KeyValue>>fromResult(kvs)); start_keys = new ArrayList<byte[]>(); stop_keys = new ArrayList<byte[]>(); final Scanner scanner = mock(Scanner.class); when(client.newScanner(any(byte[].class))).thenReturn(scanner); PowerMockito.doAnswer(new Answer<Void>() { @Override public Void answer(final InvocationOnMock invocation) throws Throwable { start_keys.add((byte[])invocation.getArguments()[0]); return null; } }).when(scanner).setStartKey(any(byte[].class)); PowerMockito.doAnswer(new Answer<Void>() { @Override public Void answer(final InvocationOnMock invocation) throws Throwable { stop_keys.add((byte[])invocation.getArguments()[0]); return null; } }).when(scanner).setStopKey(any(byte[].class)); } }