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 {@link RegionObserver#preCompact(ObserverContext, Store, InternalScanner, ScanType, 053 * 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 public TestName name = new TestName(); 064 065 /** 066 * Coprocessor that returns null when preCompact or preFlush is called. 067 */ 068 public static class TestRegionObserver implements RegionObserver, RegionCoprocessor { 069 @Override 070 public InternalScanner preFlush(ObserverContext<RegionCoprocessorEnvironment> c, Store store, 071 InternalScanner scanner, FlushLifeCycleTracker tracker) throws IOException { 072 return null; 073 } 074 075 @Override 076 public InternalScanner preCompact(ObserverContext<RegionCoprocessorEnvironment> c, Store store, 077 InternalScanner scanner, ScanType scanType, CompactionLifeCycleTracker tracker, 078 CompactionRequest request) throws IOException { 079 return null; 080 } 081 082 @Override 083 public Optional<RegionObserver> getRegionObserver() { 084 return Optional.of(this); 085 } 086 } 087 088 /** 089 * Ensure we get expected exception when we try to return null from a preFlush call. 090 * @throws IOException We expect it to throw {@link CoprocessorException} 091 */ 092 @Test (expected = CoprocessorException.class) 093 public void testPreFlushReturningNull() throws IOException { 094 RegionCoprocessorHost rch = getRegionCoprocessorHost(); 095 rch.preFlush(null, null, null); 096 } 097 098 /** 099 * Ensure we get expected exception when we try to return null from a preCompact call. 100 * @throws IOException We expect it to throw {@link CoprocessorException} 101 */ 102 @Test (expected = CoprocessorException.class) 103 public void testPreCompactReturningNull() throws IOException { 104 RegionCoprocessorHost rch = getRegionCoprocessorHost(); 105 rch.preCompact(null, null, null, null, null, null); 106 } 107 108 private RegionCoprocessorHost getRegionCoprocessorHost() { 109 // Make up an HRegion instance. Use the hbase:meta first region as our RegionInfo. Use 110 // hbase:meta table name for building the TableDescriptor our mock returns when asked schema 111 // down inside RegionCoprocessorHost. Pass in mocked RegionServerServices too. 112 RegionInfo ri = RegionInfoBuilder.FIRST_META_REGIONINFO; 113 HRegion mockedHRegion = Mockito.mock(HRegion.class); 114 Mockito.when(mockedHRegion.getRegionInfo()).thenReturn(ri); 115 TableDescriptor td = TableDescriptorBuilder.newBuilder(ri.getTable()).build(); 116 Mockito.when(mockedHRegion.getTableDescriptor()).thenReturn(td); 117 RegionServerServices mockedServices = Mockito.mock(RegionServerServices.class); 118 Configuration conf = HBaseConfiguration.create(); 119 // Load our test coprocessor defined above. 120 conf.set(REGION_COPROCESSOR_CONF_KEY, TestRegionObserver.class.getName()); 121 return new RegionCoprocessorHost(mockedHRegion, mockedServices, conf); 122 } 123}