001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.client; 019 020import static org.hamcrest.CoreMatchers.instanceOf; 021import static org.hamcrest.MatcherAssert.assertThat; 022import static org.junit.jupiter.api.Assertions.assertArrayEquals; 023import static org.junit.jupiter.api.Assertions.assertEquals; 024import static org.junit.jupiter.api.Assertions.assertFalse; 025import static org.junit.jupiter.api.Assertions.assertNull; 026import static org.junit.jupiter.api.Assertions.assertTrue; 027import static org.junit.jupiter.api.Assertions.fail; 028 029import java.io.File; 030import java.io.FileOutputStream; 031import java.io.IOException; 032import java.nio.ByteBuffer; 033import java.util.Arrays; 034import java.util.Base64; 035import java.util.List; 036import java.util.Set; 037import org.apache.hadoop.conf.Configuration; 038import org.apache.hadoop.hbase.HBaseConfiguration; 039import org.apache.hadoop.hbase.filter.Filter; 040import org.apache.hadoop.hbase.filter.FilterList; 041import org.apache.hadoop.hbase.filter.KeyOnlyFilter; 042import org.apache.hadoop.hbase.security.access.Permission; 043import org.apache.hadoop.hbase.security.visibility.Authorizations; 044import org.apache.hadoop.hbase.testclassification.ClientTests; 045import org.apache.hadoop.hbase.testclassification.SmallTests; 046import org.apache.hadoop.hbase.util.Bytes; 047import org.junit.jupiter.api.Tag; 048import org.junit.jupiter.api.Test; 049 050import org.apache.hbase.thirdparty.com.google.common.base.Throwables; 051 052import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; 053import org.apache.hadoop.hbase.shaded.protobuf.generated.ClientProtos; 054 055// TODO: cover more test cases 056@Tag(ClientTests.TAG) 057@Tag(SmallTests.TAG) 058public class TestGet { 059 060 private static final byte[] ROW = new byte[] { 'r' }; 061 062 private static final String PB_GET = "CgNyb3ciEwoPdGVzdC5Nb2NrRmlsdGVyEgAwATgB"; 063 private static final String PB_GET_WITH_FILTER_LIST = 064 "CgFyIosBCilvcmcuYXBhY2hlLmhhZG9vcC5oYmFzZS5maWx0ZXIuRmlsdGVyTGlzdBJeCAESEwoP" 065 + "dGVzdC5Nb2NrRmlsdGVyEgASEQoNbXkuTW9ja0ZpbHRlchIAEjIKLG9yZy5hcGFjaGUuaGFkb29w" 066 + "LmhiYXNlLmZpbHRlci5LZXlPbmx5RmlsdGVyEgIIADABOAE="; 067 068 private static final String MOCK_FILTER_JAR = 069 "UEsDBBQACAgIANWDlEMAAAAAAAAAAAAAAAAJAAQATUVUQS1JTkYv/soAAAMAUEsHCAAAAAACAAAA" 070 + "AAAAAFBLAwQUAAgICADVg5RDAAAAAAAAAAAAAAAAFAAAAE1FVEEtSU5GL01BTklGRVNULk1G803M" 071 + "y0xLLS7RDUstKs7Mz7NSMNQz4OVyLkpNLElN0XWqBAmY6xnEG1gqaPgXJSbnpCo45xcV5BcllgCV" 072 + "a/Jy8XIBAFBLBwgxyqRbQwAAAEQAAABQSwMEFAAICAgAUoOUQwAAAAAAAAAAAAAAABMAAABteS9N" 073 + "b2NrRmlsdGVyLmNsYXNzdZHPTsJAEMa/LYVCRVFQMd68gQc38YrxUJUTetGQGE7bstrVwjbbYsSn" 074 + "0hOJJj6AD2WcFoP/4iYzX+bb32xmd9/en18B7GPLhY11BxsurEw3GUoHaqzSQ4ZCq91nsI/0UDLU" 075 + "emoszyYjX5oL4Ufk1Hs6EFFfGJXVn6adhirJ6NGUn+rgtquiVJoOQyUWJpFdo0cMjdbAa/8hnNj3" 076 + "pqmkbmvgMbgn94GMU6XHiYMm1ed6YgJJeDbNV+fejbgTVRRRYlj+cSZDW5trLmIRhJKHYqh1zENf" 077 + "JJJf5QCfcx45DJ3/WLmYgx/LRNJ1I/UgMmMxIXbo9WxkywLLZqHsUMVJGWlxdwb2lG+XKZdys4kK" 078 + "5eocgIsl0grVy0Q5+e9Y+V75BdblDIXHX/3b3/rLWEGNdJXCJmeNop7zjQ9QSwcI1kzyMToBAADs" 079 + "AQAAUEsDBBQACAgIAFKDlEMAAAAAAAAAAAAAAAAVAAAAdGVzdC9Nb2NrRmlsdGVyLmNsYXNzdVHB" 080 + "TsJAFJwthUJFERQx3ryBBzfxivFQlRN60ZAYTtuy2tXCNtti1K/SE4kmfoAfZXwtBg3RTd6bzOy8" 081 + "zezux+frO4ADbLuwsemg6cLKcIuhdKgmKj1iKLQ7Awb7WI8kQ62vJvJ8OvaluRR+REqjrwMRDYRR" 082 + "Gf8W7TRUCUO9n8ok5Wc6uOupKJWmy1CJhUlkz+gxQ7M99Dp/eJzY9x5JZrCGHoN7+hDIOFV6kjho" 083 + "Eb/QUxNIsmeJfib3b8W9qKKIEslLpzJ0tLnhIhZBKHkoRlrHPPRFIvl1buBzn0cKQ/c/r1wk4Scy" 084 + "kXTpSD2JTFhkxC69oY1sWWBZGuoOMU7ICIt7M7CXfLtMvZSLLVSoV+cGuFghrBBfJZeT/5GV75Xf" 085 + "YF3NUHhemt/5NV/GGmqE61Q2KXWqRu7f+AJQSwcIrS5nKDoBAADyAQAAUEsBAhQAFAAICAgA1YOU" 086 + "QwAAAAACAAAAAAAAAAkABAAAAAAAAAAAAAAAAAAAAE1FVEEtSU5GL/7KAABQSwECFAAUAAgICADV" 087 + "g5RDMcqkW0MAAABEAAAAFAAAAAAAAAAAAAAAAAA9AAAATUVUQS1JTkYvTUFOSUZFU1QuTUZQSwEC" 088 + "FAAUAAgICABSg5RD1kzyMToBAADsAQAAEwAAAAAAAAAAAAAAAADCAAAAbXkvTW9ja0ZpbHRlci5j" 089 + "bGFzc1BLAQIUABQACAgIAFKDlEOtLmcoOgEAAPIBAAAVAAAAAAAAAAAAAAAAAD0CAAB0ZXN0L01v" 090 + "Y2tGaWx0ZXIuY2xhc3NQSwUGAAAAAAQABAABAQAAugMAAAAA"; 091 092 @Test 093 public void testAttributesSerialization() throws IOException { 094 Get get = new Get(Bytes.toBytes("row")); 095 get.setAttribute("attribute1", Bytes.toBytes("value1")); 096 get.setAttribute("attribute2", Bytes.toBytes("value2")); 097 get.setAttribute("attribute3", Bytes.toBytes("value3")); 098 099 ClientProtos.Get getProto = ProtobufUtil.toGet(get); 100 101 Get get2 = ProtobufUtil.toGet(getProto); 102 assertNull(get2.getAttribute("absent")); 103 assertTrue(Arrays.equals(Bytes.toBytes("value1"), get2.getAttribute("attribute1"))); 104 assertTrue(Arrays.equals(Bytes.toBytes("value2"), get2.getAttribute("attribute2"))); 105 assertTrue(Arrays.equals(Bytes.toBytes("value3"), get2.getAttribute("attribute3"))); 106 assertEquals(3, get2.getAttributesMap().size()); 107 } 108 109 @Test 110 public void testGetAttributes() { 111 Get get = new Get(ROW); 112 assertTrue(get.getAttributesMap().isEmpty()); 113 assertNull(get.getAttribute("absent")); 114 115 get.setAttribute("absent", null); 116 assertTrue(get.getAttributesMap().isEmpty()); 117 assertNull(get.getAttribute("absent")); 118 119 // adding attribute 120 get.setAttribute("attribute1", Bytes.toBytes("value1")); 121 assertTrue(Arrays.equals(Bytes.toBytes("value1"), get.getAttribute("attribute1"))); 122 assertEquals(1, get.getAttributesMap().size()); 123 assertTrue(Arrays.equals(Bytes.toBytes("value1"), get.getAttributesMap().get("attribute1"))); 124 125 // overriding attribute value 126 get.setAttribute("attribute1", Bytes.toBytes("value12")); 127 assertTrue(Arrays.equals(Bytes.toBytes("value12"), get.getAttribute("attribute1"))); 128 assertEquals(1, get.getAttributesMap().size()); 129 assertTrue(Arrays.equals(Bytes.toBytes("value12"), get.getAttributesMap().get("attribute1"))); 130 131 // adding another attribute 132 get.setAttribute("attribute2", Bytes.toBytes("value2")); 133 assertTrue(Arrays.equals(Bytes.toBytes("value2"), get.getAttribute("attribute2"))); 134 assertEquals(2, get.getAttributesMap().size()); 135 assertTrue(Arrays.equals(Bytes.toBytes("value2"), get.getAttributesMap().get("attribute2"))); 136 137 // removing attribute 138 get.setAttribute("attribute2", null); 139 assertNull(get.getAttribute("attribute2")); 140 assertEquals(1, get.getAttributesMap().size()); 141 assertNull(get.getAttributesMap().get("attribute2")); 142 143 // removing non-existed attribute 144 get.setAttribute("attribute2", null); 145 assertNull(get.getAttribute("attribute2")); 146 assertEquals(1, get.getAttributesMap().size()); 147 assertNull(get.getAttributesMap().get("attribute2")); 148 149 // removing another attribute 150 get.setAttribute("attribute1", null); 151 assertNull(get.getAttribute("attribute1")); 152 assertTrue(get.getAttributesMap().isEmpty()); 153 assertNull(get.getAttributesMap().get("attribute1")); 154 } 155 156 @Test 157 public void testNullQualifier() { 158 Get get = new Get(ROW); 159 byte[] family = Bytes.toBytes("family"); 160 get.addColumn(family, null); 161 Set<byte[]> qualifiers = get.getFamilyMap().get(family); 162 assertEquals(1, qualifiers.size()); 163 } 164 165 @Test 166 public void TestGetRowFromGetCopyConstructor() throws Exception { 167 Get get = new Get(ROW); 168 get.setFilter(null); 169 get.setAuthorizations(new Authorizations("foo")); 170 get.setACL("u", new Permission(Permission.Action.READ)); 171 get.setConsistency(Consistency.TIMELINE); 172 get.setReplicaId(2); 173 get.setIsolationLevel(IsolationLevel.READ_UNCOMMITTED); 174 get.setCheckExistenceOnly(true); 175 get.setTimeRange(3, 4); 176 get.readVersions(11); 177 get.setMaxResultsPerColumnFamily(10); 178 get.setRowOffsetPerColumnFamily(11); 179 get.setCacheBlocks(true); 180 get.setQueryMetricsEnabled(true); 181 182 Get copyGet = new Get(get); 183 assertEquals(0, Bytes.compareTo(get.getRow(), copyGet.getRow())); 184 185 // from OperationWithAttributes 186 assertEquals(get.getId(), copyGet.getId()); 187 188 // from Query class 189 assertEquals(get.getFilter(), copyGet.getFilter()); 190 assertTrue(get.getAuthorizations().toString().equals(copyGet.getAuthorizations().toString())); 191 assertTrue(Bytes.equals(get.getACL(), copyGet.getACL())); 192 assertEquals(get.getConsistency(), copyGet.getConsistency()); 193 assertEquals(get.getReplicaId(), copyGet.getReplicaId()); 194 assertEquals(get.getIsolationLevel(), copyGet.getIsolationLevel()); 195 assertTrue(get.isQueryMetricsEnabled()); 196 197 // from Get class 198 assertEquals(get.isCheckExistenceOnly(), copyGet.isCheckExistenceOnly()); 199 assertTrue(get.getTimeRange().equals(copyGet.getTimeRange())); 200 assertEquals(get.getMaxVersions(), copyGet.getMaxVersions()); 201 assertEquals(get.getMaxResultsPerColumnFamily(), copyGet.getMaxResultsPerColumnFamily()); 202 assertEquals(get.getRowOffsetPerColumnFamily(), copyGet.getRowOffsetPerColumnFamily()); 203 assertEquals(get.getCacheBlocks(), copyGet.getCacheBlocks()); 204 assertEquals(get.getId(), copyGet.getId()); 205 } 206 207 @Test 208 public void testDynamicFilter() throws Exception { 209 Configuration conf = HBaseConfiguration.create(); 210 String localPath = conf.get("hbase.local.dir") + File.separator + "jars" + File.separator; 211 File jarFile = new File(localPath, "MockFilter.jar"); 212 jarFile.delete(); 213 assertFalse(jarFile.exists(), "Should be deleted: " + jarFile.getPath()); 214 215 ClientProtos.Get getProto1 = ClientProtos.Get.parseFrom(Base64.getDecoder().decode(PB_GET)); 216 ClientProtos.Get getProto2 = 217 ClientProtos.Get.parseFrom(Base64.getDecoder().decode(PB_GET_WITH_FILTER_LIST)); 218 try { 219 ProtobufUtil.toGet(getProto1); 220 fail("Should not be able to load the filter class"); 221 } catch (IOException ioe) { 222 assertTrue(ioe.getCause() instanceof ClassNotFoundException); 223 } 224 try { 225 ProtobufUtil.toGet(getProto2); 226 fail("Should not be able to load the filter class"); 227 } catch (IOException ioe) { 228 // This test is deserializing a FilterList, and one of the sub-filters is not found. 229 // So the actual caused by is buried a few levels deep. 230 assertThat(Throwables.getRootCause(ioe), instanceOf(ClassNotFoundException.class)); 231 } 232 FileOutputStream fos = new FileOutputStream(jarFile); 233 fos.write(Base64.getDecoder().decode(MOCK_FILTER_JAR)); 234 fos.close(); 235 236 Get get1 = ProtobufUtil.toGet(getProto1); 237 assertEquals("test.MockFilter", get1.getFilter().getClass().getName()); 238 239 Get get2 = ProtobufUtil.toGet(getProto2); 240 assertTrue(get2.getFilter() instanceof FilterList); 241 List<Filter> filters = ((FilterList) get2.getFilter()).getFilters(); 242 assertEquals(3, filters.size()); 243 assertEquals("test.MockFilter", filters.get(0).getClass().getName()); 244 assertEquals("my.MockFilter", filters.get(1).getClass().getName()); 245 assertTrue(filters.get(2) instanceof KeyOnlyFilter); 246 } 247 248 @Test 249 public void testGetRowConstructor() { 250 byte[] row1 = Bytes.toBytes("testRow"); 251 byte[] row2 = Bytes.toBytes("testtestRow"); 252 ByteBuffer rowBuffer = ByteBuffer.wrap(row1); 253 Get get1 = new Get(rowBuffer); 254 Get get2 = new Get(row2, 4, 7); 255 assertArrayEquals(get1.getRow(), get2.getRow()); 256 } 257}