/* * Copyright The Apache Software Foundation * * 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.hbase.regionserver.metrics; import static org.junit.Assert.*; import java.util.regex.Pattern; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hbase.HBaseConfiguration; import org.apache.hadoop.hbase.SmallTests; import org.apache.hadoop.hbase.regionserver.HRegion; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONStringer; import org.junit.Test; import org.junit.experimental.categories.Category; @Category(SmallTests.class) public class TestSchemaConfigured { private static final Log LOG = LogFactory.getLog(TestSchemaConfigured.class); private final String TABLE_NAME = "myTable"; private final String CF_NAME = "myColumnFamily"; private static final Path TMP_HFILE_PATH = new Path( "/hbase/myTable/myRegion/" + HRegion.REGION_TEMP_SUBDIR + "/hfilename"); /** Test if toString generates real JSON */ @Test public void testToString() throws JSONException { SchemaConfigured sc = new SchemaConfigured(null, TABLE_NAME, CF_NAME); JSONStringer json = new JSONStringer(); json.object(); json.key("tableName"); json.value(TABLE_NAME); json.key("cfName"); json.value(CF_NAME); json.endObject(); assertEquals(json.toString(), sc.schemaConfAsJSON()); } /** Don't allow requesting metrics before setting table/CF name */ @Test public void testDelayedInitialization() { SchemaConfigured unconfigured = new SchemaConfigured(); try { unconfigured.getSchemaMetrics(); fail(IllegalStateException.class.getSimpleName() + " expected"); } catch (IllegalStateException ex) { assertTrue("Unexpected exception message: " + ex.getMessage(), Pattern.matches(".* metrics requested before .* initialization.*", ex.getMessage())); LOG.debug("Expected exception: " + ex.getMessage()); } SchemaMetrics.setUseTableNameInTest(false); SchemaConfigured other = new SchemaConfigured(null, TABLE_NAME, CF_NAME); other.passSchemaMetricsTo(unconfigured); unconfigured.getSchemaMetrics(); // now this should succeed } /** Don't allow setting table/CF name twice */ @Test public void testInitializingTwice() { Configuration conf = HBaseConfiguration.create(); for (int i = 0; i < 4; ++i) { SchemaConfigured sc = new SchemaConfigured(conf, TABLE_NAME, CF_NAME); SchemaConfigured target = new SchemaConfigured(conf, TABLE_NAME + (i % 2 == 1 ? "1" : ""), CF_NAME + ((i & 2) != 0 ? "1" : "")); if (i == 0) { sc.passSchemaMetricsTo(target); // No exception expected. continue; } String testDesc = "Trying to re-configure " + target.schemaConfAsJSON() + " with " + sc.schemaConfAsJSON(); try { sc.passSchemaMetricsTo(target); fail(IllegalArgumentException.class.getSimpleName() + " expected"); } catch (IllegalArgumentException ex) { final String errorMsg = testDesc + ". Unexpected exception message: " + ex.getMessage(); final String exceptionRegex = "Trying to change table .* CF .*"; assertTrue(errorMsg, Pattern.matches(exceptionRegex, ex.getMessage())); LOG.debug("Expected exception: " + ex.getMessage()); } } } @Test(expected=IllegalStateException.class) public void testConfigureWithUnconfigured1() { SchemaConfigured unconfigured = new SchemaConfigured(null, "t1", null); SchemaConfigured target = new SchemaConfigured(); unconfigured.passSchemaMetricsTo(target); } @Test(expected=IllegalStateException.class) public void testConfigureWithUnconfigured2() { SchemaConfigured unconfigured = new SchemaConfigured(null, null, "cf1"); SchemaConfigured target = new SchemaConfigured(); unconfigured.passSchemaMetricsTo(target); } /** * Configuring with an uninitialized object is equivalent to re-setting * schema metrics configuration. */ public void testConfigureWithNull() { SchemaConfigured unconfigured = new SchemaConfigured(); SchemaConfigured target = new SchemaConfigured(null, "t1", "cf1"); unconfigured.passSchemaMetricsTo(target); assertTrue(target.getTableName() == null); assertTrue(target.getColumnFamilyName() == null); } public void testConfigurePartiallyDefined() { final SchemaConfigured sc = new SchemaConfigured(null, "t1", "cf1"); final SchemaConfigured target1 = new SchemaConfigured(null, "t2", null); sc.passSchemaMetricsTo(target1); assertEquals("t2", target1.getColumnFamilyName()); assertEquals("cf1", target1.getColumnFamilyName()); final SchemaConfigured target2 = new SchemaConfigured(null, null, "cf2"); sc.passSchemaMetricsTo(target2); assertEquals("t1", target2.getColumnFamilyName()); assertEquals("cf2", target2.getColumnFamilyName()); final SchemaConfigured target3 = new SchemaConfigured(null, null, null); sc.passSchemaMetricsTo(target3); assertEquals("t1", target2.getColumnFamilyName()); assertEquals("cf1", target2.getColumnFamilyName()); } @Test(expected=IllegalArgumentException.class) public void testConflictingConf() { SchemaConfigured sc = new SchemaConfigured(null, "t1", "cf1"); SchemaConfigured target = new SchemaConfigured(null, "t2", "cf1"); sc.passSchemaMetricsTo(target); } /** We allow setting CF to unknown and then reconfiguring it */ public void testReconfigureUnknownCF() { SchemaConfigured sc = new SchemaConfigured(null, "t1", "cf1"); SchemaConfigured target = new SchemaConfigured(null, "t1", SchemaMetrics.UNKNOWN); sc.passSchemaMetricsTo(target); } /** * When the "column family" deduced from the path is ".tmp" (this happens * for files written on compaction) we allow re-setting the CF to another * value. */ @Test public void testTmpPath() { SchemaConfigured sc = new SchemaConfigured(null, "myTable", "myCF"); SchemaConfigured target = new SchemaConfigured(TMP_HFILE_PATH); sc.passSchemaMetricsTo(target); } /** * Even if CF is initially undefined (".tmp"), we don't allow to change * table name. */ @Test(expected=IllegalArgumentException.class) public void testTmpPathButInvalidTable() { SchemaConfigured sc = new SchemaConfigured(null, "anotherTable", "myCF"); SchemaConfigured target = new SchemaConfigured(TMP_HFILE_PATH); sc.passSchemaMetricsTo(target); } @Test public void testSchemaConfigurationHook() { SchemaConfigured sc = new SchemaConfigured(null, "myTable", "myCF"); final StringBuilder newCF = new StringBuilder(); final StringBuilder newTable = new StringBuilder(); SchemaConfigured target = new SchemaConfigured() { @Override protected void schemaConfigurationChanged() { newCF.append(getColumnFamilyName()); newTable.append(getTableName()); } }; sc.passSchemaMetricsTo(target); assertEquals("myTable", newTable.toString()); assertEquals("myCF", newCF.toString()); } @Test public void testResetSchemaMetricsConf() { SchemaConfigured target = new SchemaConfigured(null, "t1", "cf1"); SchemaConfigured.resetSchemaMetricsConf(target); new SchemaConfigured(null, "t2", "cf2").passSchemaMetricsTo(target); assertEquals("t2", target.getTableName()); assertEquals("cf2", target.getColumnFamilyName()); } @Test public void testPathTooShort() { // This has too few path components (four, the first one is empty). SchemaConfigured sc1 = new SchemaConfigured(new Path("/a/b/c/d")); assertEquals(SchemaMetrics.UNKNOWN, sc1.getTableName()); assertEquals(SchemaMetrics.UNKNOWN, sc1.getColumnFamilyName()); SchemaConfigured sc2 = new SchemaConfigured(new Path("a/b/c/d")); assertEquals(SchemaMetrics.UNKNOWN, sc2.getTableName()); assertEquals(SchemaMetrics.UNKNOWN, sc2.getColumnFamilyName()); SchemaConfigured sc3 = new SchemaConfigured( new Path("/hbase/tableName/regionId/cfName/hfileName")); assertEquals("tableName", sc3.getTableName()); assertEquals("cfName", sc3.getColumnFamilyName()); SchemaConfigured sc4 = new SchemaConfigured( new Path("hbase/tableName/regionId/cfName/hfileName")); assertEquals("tableName", sc4.getTableName()); assertEquals("cfName", sc4.getColumnFamilyName()); } @org.junit.Rule public org.apache.hadoop.hbase.ResourceCheckerJUnitRule cu = new org.apache.hadoop.hbase.ResourceCheckerJUnitRule(); }