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 static org.junit.Assert.assertArrayEquals;
021import static org.junit.Assert.assertEquals;
022import static org.junit.Assert.assertSame;
023import static org.junit.Assert.fail;
024
025import java.nio.ByteBuffer;
026import java.util.HashMap;
027import java.util.Map;
028import org.apache.hadoop.hbase.testclassification.MediumTests;
029import org.apache.hadoop.hbase.testclassification.MiscTests;
030import org.apache.hadoop.hbase.util.Bytes;
031import org.junit.ClassRule;
032import org.junit.Test;
033import org.junit.experimental.categories.Category;
034import org.junit.rules.TestWatcher;
035import org.junit.runner.Description;
036
037/**
038 * Returns a {@code byte[]} containing the name of the currently running test method.
039 */
040@Category({MiscTests.class, MediumTests.class})
041public class TestTableName extends TestWatcher {
042
043  @ClassRule
044  public static final HBaseClassTestRule CLASS_RULE =
045      HBaseClassTestRule.forClass(TestTableName.class);
046
047  private TableName tableName;
048
049  /**
050   * Invoked when a test is about to start
051   */
052  @Override
053  protected void starting(Description description) {
054    tableName = TableName.valueOf(description.getMethodName());
055  }
056
057  public TableName getTableName() {
058    return tableName;
059  }
060
061  String[] emptyNames = {"", " "};
062  String[] invalidNamespace = {":a", "%:a"};
063  String[] legalTableNames = {"foo", "with-dash_under.dot", "_under_start_ok",
064    "with-dash.with_underscore", "02-01-2012.my_table_01-02", "xyz._mytable_", "9_9_0.table_02",
065    "dot1.dot2.table", "new.-mytable", "with-dash.with.dot", "legal..t2", "legal..legal.t2",
066    "trailingdots..", "trailing.dots...", "ns:mytable", "ns:_mytable_", "ns:my_table_01-02"};
067  String[] illegalTableNames = {".dot_start_illegal", "-dash_start_illegal", "spaces not ok",
068    "-dash-.start_illegal", "new.table with space", "01 .table", "ns:-illegaldash",
069    "new:.illegaldot", "new:illegalcolon1:", "new:illegalcolon1:2"};
070
071
072  @Test(expected = IllegalArgumentException.class)
073  public void testInvalidNamespace() {
074    for (String tn : invalidNamespace) {
075      TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn));
076      fail("invalid namespace " + tn
077          + " should have failed with IllegalArgumentException for namespace");
078    }
079  }
080
081  @Test(expected = IllegalArgumentException.class)
082  public void testEmptyNamespaceName() {
083    for (String nn : emptyNames) {
084      TableName.isLegalNamespaceName(Bytes.toBytes(nn));
085      fail("invalid Namespace name " + nn + " should have failed with IllegalArgumentException");
086    }
087  }
088
089  @Test(expected = IllegalArgumentException.class)
090  public void testEmptyTableName() {
091    for (String tn : emptyNames) {
092      TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn));
093      fail("invalid tablename " + tn + " should have failed with IllegalArgumentException");
094    }
095  }
096
097  @Test
098  public void testLegalHTableNames() {
099    for (String tn : legalTableNames) {
100      TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn));
101    }
102  }
103
104  @Test
105  public void testIllegalHTableNames() {
106    for (String tn : illegalTableNames) {
107      try {
108        TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn));
109        fail("invalid tablename " + tn + " should have failed");
110      } catch (Exception e) {
111        // expected
112      }
113    }
114  }
115
116  static class Names {
117    String ns;
118    byte[] nsb;
119    String tn;
120    byte[] tnb;
121    String nn;
122    byte[] nnb;
123
124    Names(String ns, String tn) {
125      this.ns = ns;
126      nsb = Bytes.toBytes(ns);
127      this.tn = tn;
128      tnb = Bytes.toBytes(tn);
129      nn = this.ns + ":" + this.tn;
130      nnb = Bytes.toBytes(nn);
131    }
132
133    @Override
134    public boolean equals(Object o) {
135      if (this == o) {
136        return true;
137      }
138      if (o == null || getClass() != o.getClass()) {
139        return false;
140      }
141
142      Names names = (Names) o;
143
144      if (!ns.equals(names.ns)) {
145        return false;
146      }
147      if (!tn.equals(names.tn)) {
148        return false;
149      }
150
151      return true;
152    }
153
154    @Override
155    public int hashCode() {
156      int result = ns.hashCode();
157      result = 31 * result + tn.hashCode();
158      return result;
159    }
160  }
161
162  Names[] names = new Names[] {
163    new Names("n1", "n1"),
164    new Names("n2", "n2"),
165    new Names("table1", "table1"),
166    new Names("table2", "table2"),
167    new Names("table2", "table1"),
168    new Names("table1", "table2"),
169    new Names("n1", "table1"),
170    new Names("n1", "table1"),
171    new Names("n2", "table2"),
172    new Names("n2", "table2")
173  };
174
175  @Test
176  public void testValueOf() {
177
178    Map<String, TableName> inCache = new HashMap<>();
179    // fill cache
180    for (Names name : names) {
181      inCache.put(name.nn, TableName.valueOf(name.ns, name.tn));
182    }
183    for (Names name : names) {
184      assertSame(inCache.get(name.nn), validateNames(TableName.valueOf(name.ns, name.tn), name));
185      assertSame(inCache.get(name.nn), validateNames(TableName.valueOf(name.nsb, name.tnb), name));
186      assertSame(inCache.get(name.nn), validateNames(TableName.valueOf(name.nn), name));
187      assertSame(inCache.get(name.nn), validateNames(TableName.valueOf(name.nnb), name));
188      assertSame(inCache.get(name.nn), validateNames(TableName.valueOf(
189          ByteBuffer.wrap(name.nsb), ByteBuffer.wrap(name.tnb)), name));
190    }
191
192  }
193
194  private TableName validateNames(TableName expected, Names names) {
195    assertEquals(expected.getNameAsString(), names.nn);
196    assertArrayEquals(expected.getName(), names.nnb);
197    assertEquals(expected.getQualifierAsString(), names.tn);
198    assertArrayEquals(expected.getQualifier(), names.tnb);
199    assertEquals(expected.getNamespaceAsString(), names.ns);
200    assertArrayEquals(expected.getNamespace(), names.nsb);
201    return expected;
202  }
203
204}