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.coprocessor; 019 020import static org.apache.hadoop.hbase.coprocessor.CoprocessorHost.REGION_COPROCESSOR_CONF_KEY; 021 022import java.io.IOException; 023import java.util.Optional; 024import org.apache.hadoop.conf.Configuration; 025import org.apache.hadoop.hbase.HBaseClassTestRule; 026import org.apache.hadoop.hbase.HBaseConfiguration; 027import org.apache.hadoop.hbase.client.RegionInfo; 028import org.apache.hadoop.hbase.client.RegionInfoBuilder; 029import org.apache.hadoop.hbase.client.TableDescriptor; 030import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 031import org.apache.hadoop.hbase.regionserver.FlushLifeCycleTracker; 032import org.apache.hadoop.hbase.regionserver.HRegion; 033import org.apache.hadoop.hbase.regionserver.InternalScanner; 034import org.apache.hadoop.hbase.regionserver.RegionCoprocessorHost; 035import org.apache.hadoop.hbase.regionserver.RegionServerServices; 036import org.apache.hadoop.hbase.regionserver.ScanType; 037import org.apache.hadoop.hbase.regionserver.Store; 038import org.apache.hadoop.hbase.regionserver.compactions.CompactionLifeCycleTracker; 039import org.apache.hadoop.hbase.regionserver.compactions.CompactionRequest; 040import org.apache.hadoop.hbase.testclassification.CoprocessorTests; 041import org.apache.hadoop.hbase.testclassification.SmallTests; 042import org.junit.ClassRule; 043import org.junit.Rule; 044import org.junit.Test; 045import org.junit.experimental.categories.Category; 046import org.junit.rules.TestName; 047import org.mockito.Mockito; 048 049/** 050 * Test that we fail if a Coprocessor tries to return a null scanner out 051 * {@link RegionObserver#preFlush(ObserverContext, Store, InternalScanner, FlushLifeCycleTracker)} 052 * or 053 * {@link RegionObserver#preCompact(ObserverContext, Store, InternalScanner, ScanType, CompactionLifeCycleTracker, CompactionRequest)} 054 * @see <a href=https://issues.apache.org/jira/browse/HBASE-19122>HBASE-19122</a> 055 */ 056@Category({ CoprocessorTests.class, SmallTests.class }) 057public class TestRegionObserverPreFlushAndPreCompact { 058 059 @ClassRule 060 public static final HBaseClassTestRule CLASS_RULE = 061 HBaseClassTestRule.forClass(TestRegionObserverPreFlushAndPreCompact.class); 062 063 @Rule 064 public TestName name = new TestName(); 065 066 /** 067 * Coprocessor that returns null when preCompact or preFlush is called. 068 */ 069 public static class TestRegionObserver implements RegionObserver, RegionCoprocessor { 070 @Override 071 public InternalScanner preFlush(ObserverContext<? extends RegionCoprocessorEnvironment> c, 072 Store store, InternalScanner scanner, FlushLifeCycleTracker tracker) throws IOException { 073 return null; 074 } 075 076 @Override 077 public InternalScanner preCompact(ObserverContext<? extends RegionCoprocessorEnvironment> c, 078 Store store, InternalScanner scanner, ScanType scanType, CompactionLifeCycleTracker tracker, 079 CompactionRequest request) throws IOException { 080 return null; 081 } 082 083 @Override 084 public Optional<RegionObserver> getRegionObserver() { 085 return Optional.of(this); 086 } 087 } 088 089 /** 090 * Ensure we get expected exception when we try to return null from a preFlush call. 091 * @throws IOException We expect it to throw {@link CoprocessorException} 092 */ 093 @Test(expected = CoprocessorException.class) 094 public void testPreFlushReturningNull() throws IOException { 095 RegionCoprocessorHost rch = getRegionCoprocessorHost(); 096 rch.preFlush(null, null, null); 097 } 098 099 /** 100 * Ensure we get expected exception when we try to return null from a preCompact call. 101 * @throws IOException We expect it to throw {@link CoprocessorException} 102 */ 103 @Test(expected = CoprocessorException.class) 104 public void testPreCompactReturningNull() throws IOException { 105 RegionCoprocessorHost rch = getRegionCoprocessorHost(); 106 rch.preCompact(null, null, null, null, null, null); 107 } 108 109 private RegionCoprocessorHost getRegionCoprocessorHost() { 110 // Make up an HRegion instance. Use the hbase:meta first region as our RegionInfo. Use 111 // hbase:meta table name for building the TableDescriptor our mock returns when asked schema 112 // down inside RegionCoprocessorHost. Pass in mocked RegionServerServices too. 113 RegionInfo ri = RegionInfoBuilder.FIRST_META_REGIONINFO; 114 HRegion mockedHRegion = Mockito.mock(HRegion.class); 115 Mockito.when(mockedHRegion.getRegionInfo()).thenReturn(ri); 116 TableDescriptor td = TableDescriptorBuilder.newBuilder(ri.getTable()).build(); 117 Mockito.when(mockedHRegion.getTableDescriptor()).thenReturn(td); 118 RegionServerServices mockedServices = Mockito.mock(RegionServerServices.class); 119 Configuration conf = HBaseConfiguration.create(); 120 // Load our test coprocessor defined above. 121 conf.set(REGION_COPROCESSOR_CONF_KEY, TestRegionObserver.class.getName()); 122 return new RegionCoprocessorHost(mockedHRegion, mockedServices, conf); 123 } 124}