/** * 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.hadoop.hive.metastore.hbase; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hbase.client.Delete; import org.apache.hadoop.hbase.client.Get; import org.apache.hadoop.hbase.client.HTableInterface; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.Result; import org.apache.hadoop.hbase.client.ResultScanner; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hive.conf.HiveConf; import org.apache.hadoop.hive.conf.HiveConf.ConfVars; import org.apache.hadoop.hive.metastore.FileFormatProxy; import org.apache.hadoop.hive.metastore.PartitionExpressionProxy; import org.apache.hadoop.hive.metastore.api.FileMetadataExprType; import org.apache.hadoop.hive.metastore.api.MetaException; import org.apache.hadoop.hive.ql.io.sarg.SearchArgument; import org.apache.hadoop.hive.serde2.typeinfo.PrimitiveTypeInfo; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.SortedMap; /** * Mock utilities for HBaseStore testing */ public class MockUtils { /** * The default impl is in ql package and is not available in unit tests. */ public static class NOOPProxy implements PartitionExpressionProxy { @Override public String convertExprToFilter(byte[] expr) throws MetaException { return null; } @Override public boolean filterPartitionsByExpr(List<String> partColumnNames, List<PrimitiveTypeInfo> partColumnTypeInfos, byte[] expr, String defaultPartitionName, List<String> partitionNames) throws MetaException { return false; } @Override public SearchArgument createSarg(byte[] expr) { return null; } @Override public FileMetadataExprType getMetadataType(String inputFormat) { return null; } @Override public FileFormatProxy getFileFormatProxy(FileMetadataExprType type) { return null; } } static HBaseStore init(Configuration conf, HTableInterface htable, final SortedMap<String, Cell> rows) throws IOException { ((HiveConf)conf).setVar(ConfVars.METASTORE_EXPRESSION_PROXY_CLASS, NOOPProxy.class.getName()); Mockito.when(htable.get(Mockito.any(Get.class))).thenAnswer(new Answer<Result>() { @Override public Result answer(InvocationOnMock invocation) throws Throwable { Get get = (Get) invocation.getArguments()[0]; Cell cell = rows.get(new String(get.getRow())); if (cell == null) { return new Result(); } else { return Result.create(new Cell[]{cell}); } } }); Mockito.when(htable.get(Mockito.anyListOf(Get.class))).thenAnswer(new Answer<Result[]>() { @Override public Result[] answer(InvocationOnMock invocation) throws Throwable { @SuppressWarnings("unchecked") List<Get> gets = (List<Get>) invocation.getArguments()[0]; Result[] results = new Result[gets.size()]; for (int i = 0; i < gets.size(); i++) { Cell cell = rows.get(new String(gets.get(i).getRow())); Result result; if (cell == null) { result = new Result(); } else { result = Result.create(new Cell[]{cell}); } results[i] = result; } return results; } }); Mockito.when(htable.getScanner(Mockito.any(Scan.class))).thenAnswer(new Answer<ResultScanner>() { @Override public ResultScanner answer(InvocationOnMock invocation) throws Throwable { Scan scan = (Scan)invocation.getArguments()[0]; List<Result> results = new ArrayList<Result>(); String start = new String(scan.getStartRow()); String stop = new String(scan.getStopRow()); SortedMap<String, Cell> sub = rows.subMap(start, stop); for (Map.Entry<String, Cell> e : sub.entrySet()) { results.add(Result.create(new Cell[]{e.getValue()})); } final Iterator<Result> iter = results.iterator(); return new ResultScanner() { @Override public Result next() throws IOException { return null; } @Override public Result[] next(int nbRows) throws IOException { return new Result[0]; } @Override public void close() { } @Override public Iterator<Result> iterator() { return iter; } }; } }); Mockito.doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Put put = (Put)invocation.getArguments()[0]; rows.put(new String(put.getRow()), put.getFamilyCellMap().firstEntry().getValue().get(0)); return null; } }).when(htable).put(Mockito.any(Put.class)); Mockito.when(htable.checkAndPut(Mockito.any(byte[].class), Mockito.any(byte[].class), Mockito.any(byte[].class), Mockito.any(byte[].class), Mockito.any(Put.class))).thenAnswer( new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { // Always say it succeeded and overwrite Put put = (Put)invocation.getArguments()[4]; rows.put(new String(put.getRow()), put.getFamilyCellMap().firstEntry().getValue().get(0)); return true; } }); Mockito.doAnswer(new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) throws Throwable { Delete del = (Delete)invocation.getArguments()[0]; rows.remove(new String(del.getRow())); return null; } }).when(htable).delete(Mockito.any(Delete.class)); Mockito.when(htable.checkAndDelete(Mockito.any(byte[].class), Mockito.any(byte[].class), Mockito.any(byte[].class), Mockito.any(byte[].class), Mockito.any(Delete.class))).thenAnswer( new Answer<Boolean>() { @Override public Boolean answer(InvocationOnMock invocation) throws Throwable { // Always say it succeeded Delete del = (Delete)invocation.getArguments()[4]; rows.remove(new String(del.getRow())); return true; } }); // Mock connection HBaseConnection hconn = Mockito.mock(HBaseConnection.class); Mockito.when(hconn.getHBaseTable(Mockito.anyString())).thenReturn(htable); HiveConf.setVar(conf, HiveConf.ConfVars.METASTORE_HBASE_CONNECTION_CLASS, HBaseReadWrite.TEST_CONN); HBaseReadWrite.setTestConnection(hconn); HBaseReadWrite.setConf(conf); HBaseStore store = new HBaseStore(); store.setConf(conf); return store; } }