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; 019 020import java.io.IOException; 021import java.util.concurrent.CompletableFuture; 022import org.apache.hadoop.conf.Configuration; 023import org.apache.hadoop.hbase.client.AsyncConnection; 024import org.apache.hadoop.hbase.client.ConnectionFactory; 025import org.junit.ClassRule; 026import org.junit.Rule; 027import org.junit.rules.ExternalResource; 028import org.junit.rules.TestRule; 029 030/** 031 * A {@link TestRule} that manages an instance of the {@link MiniHBaseCluster}. Can be used in 032 * either the {@link Rule} or {@link ClassRule} positions. Built on top of an instance of 033 * {@link HBaseTestingUtility}, so be weary of intermixing direct use of that class with this Rule. 034 * </p> 035 * Use in combination with {@link ConnectionRule}, for example: 036 * 037 * <pre>{@code 038 * public class TestMyClass { 039 * @ClassRule 040 * public static final MiniClusterRule miniClusterRule = MiniClusterRule.newBuilder().build(); 041 * 042 * @Rule 043 * public final ConnectionRule connectionRule = 044 * new ConnectionRule(miniClusterRule::createConnection); 045 * } 046 * }</pre> 047 */ 048public final class MiniClusterRule extends ExternalResource { 049 050 /** 051 * A builder for fluent composition of a new {@link MiniClusterRule}. 052 */ 053 public static class Builder { 054 055 private StartMiniClusterOption miniClusterOption; 056 private Configuration conf; 057 058 /** 059 * Use the provided {@link StartMiniClusterOption} to construct the {@link MiniHBaseCluster}. 060 */ 061 public Builder setMiniClusterOption(final StartMiniClusterOption miniClusterOption) { 062 this.miniClusterOption = miniClusterOption; 063 return this; 064 } 065 066 /** 067 * Seed the underlying {@link HBaseTestingUtility} with the provided {@link Configuration}. 068 */ 069 public Builder setConfiguration(final Configuration conf) { 070 this.conf = conf; 071 return this; 072 } 073 074 public MiniClusterRule build() { 075 return new MiniClusterRule( 076 conf, 077 miniClusterOption != null 078 ? miniClusterOption 079 : StartMiniClusterOption.builder().build()); 080 } 081 } 082 083 private final HBaseTestingUtility testingUtility; 084 private final StartMiniClusterOption miniClusterOptions; 085 086 private MiniHBaseCluster miniCluster; 087 088 private MiniClusterRule(final Configuration conf, 089 final StartMiniClusterOption miniClusterOptions) { 090 this.testingUtility = new HBaseTestingUtility(conf); 091 this.miniClusterOptions = miniClusterOptions; 092 } 093 094 public static Builder newBuilder() { 095 return new Builder(); 096 } 097 098 /** 099 * @return the underlying instance of {@link HBaseTestingUtility} 100 */ 101 public HBaseTestingUtility getTestingUtility() { 102 return testingUtility; 103 } 104 105 /** 106 * Create a {@link AsyncConnection} to the managed {@link MiniHBaseCluster}. It's up to the caller 107 * to {@link AsyncConnection#close() close()} the connection when finished. 108 */ 109 public CompletableFuture<AsyncConnection> createConnection() { 110 if (miniCluster == null) { 111 throw new IllegalStateException("test cluster not initialized"); 112 } 113 return ConnectionFactory.createAsyncConnection(miniCluster.getConf()); 114 } 115 116 @Override 117 protected void before() throws Throwable { 118 miniCluster = testingUtility.startMiniCluster(miniClusterOptions); 119 } 120 121 @Override 122 protected void after() { 123 try { 124 testingUtility.shutdownMiniCluster(); 125 } catch (IOException e) { 126 throw new RuntimeException(e); 127 } 128 } 129}