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.jupiter.api.Assertions.assertArrayEquals;
021import static org.junit.jupiter.api.Assertions.assertEquals;
022import static org.junit.jupiter.api.Assertions.assertSame;
023import static org.junit.jupiter.api.Assertions.assertThrows;
024
025import java.nio.ByteBuffer;
026import java.util.HashMap;
027import java.util.Map;
028import org.apache.hadoop.hbase.testclassification.MiscTests;
029import org.apache.hadoop.hbase.testclassification.SmallTests;
030import org.apache.hadoop.hbase.util.Bytes;
031import org.junit.jupiter.api.Tag;
032import org.junit.jupiter.api.Test;
033
034/**
035 * Tests for various kinds of TableNames.
036 */
037@Tag(MiscTests.TAG)
038@Tag(SmallTests.TAG)
039public class TestTableName {
040
041  private static String[] emptyNames = { "", " " };
042  private static String[] invalidNamespace = { ":a", "%:a" };
043  private static String[] legalTableNames = { "foo", "with-dash_under.dot", "_under_start_ok",
044    "with-dash.with_underscore", "02-01-2012.my_table_01-02", "xyz._mytable_", "9_9_0.table_02",
045    "dot1.dot2.table", "new.-mytable", "with-dash.with.dot", "legal..t2", "legal..legal.t2",
046    "trailingdots..", "trailing.dots...", "ns:mytable", "ns:_mytable_", "ns:my_table_01-02" };
047  private static String[] illegalTableNames = { ".dot_start_illegal", "-dash_start_illegal",
048    "spaces not ok", "-dash-.start_illegal", "new.table with space", "01 .table", "ns:-illegaldash",
049    "new:.illegaldot", "new:illegalcolon1:", "new:illegalcolon1:2" };
050
051  static class Names {
052    String ns;
053    byte[] nsb;
054    String tn;
055    byte[] tnb;
056    String nn;
057    byte[] nnb;
058
059    Names(String ns, String tn) {
060      this.ns = ns;
061      nsb = Bytes.toBytes(ns);
062      this.tn = tn;
063      tnb = Bytes.toBytes(tn);
064      nn = this.ns + ":" + this.tn;
065      nnb = Bytes.toBytes(nn);
066    }
067
068    @Override
069    public boolean equals(Object o) {
070      if (this == o) {
071        return true;
072      }
073      if (!(o instanceof Names)) {
074        return false;
075      }
076      Names names = (Names) o;
077      if (!ns.equals(names.ns)) {
078        return false;
079      }
080      if (!tn.equals(names.tn)) {
081        return false;
082      }
083      return true;
084    }
085
086    @Override
087    public int hashCode() {
088      int result = ns.hashCode();
089      result = 31 * result + tn.hashCode();
090      return result;
091    }
092  }
093
094  private static Names[] names = new Names[] { new Names("n1", "n1"), new Names("n2", "n2"),
095    new Names("table1", "table1"), new Names("table2", "table2"), new Names("table2", "table1"),
096    new Names("table1", "table2"), new Names("n1", "table1"), new Names("n1", "table1"),
097    new Names("n2", "table2"), new Names("n2", "table2") };
098
099  @Test
100  public void testInvalidNamespace() {
101    for (String tn : invalidNamespace) {
102      assertThrows(IllegalArgumentException.class,
103        () -> TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn)));
104    }
105  }
106
107  @Test
108  public void testEmptyNamespaceName() {
109    for (String nn : emptyNames) {
110      assertThrows(IllegalArgumentException.class,
111        () -> TableName.isLegalNamespaceName(Bytes.toBytes(nn)));
112    }
113  }
114
115  @Test
116  public void testEmptyTableName() {
117    for (String tn : emptyNames) {
118      assertThrows(IllegalArgumentException.class,
119        () -> TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn)));
120    }
121  }
122
123  @Test
124  public void testLegalHTableNames() {
125    for (String tn : legalTableNames) {
126      TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn));
127    }
128  }
129
130  @Test
131  public void testIllegalHTableNames() {
132    for (String tn : illegalTableNames) {
133      assertThrows(IllegalArgumentException.class,
134        () -> TableName.isLegalFullyQualifiedTableName(Bytes.toBytes(tn)));
135    }
136  }
137
138  @Test
139  public void testValueOf() {
140    Map<String, TableName> inCache = new HashMap<>();
141    // fill cache
142    for (Names name : names) {
143      inCache.put(name.nn, TableName.valueOf(name.ns, name.tn));
144    }
145    for (Names name : names) {
146      assertSame(inCache.get(name.nn), validateNames(TableName.valueOf(name.ns, name.tn), name));
147      assertSame(inCache.get(name.nn), validateNames(TableName.valueOf(name.nsb, name.tnb), name));
148      assertSame(inCache.get(name.nn), validateNames(TableName.valueOf(name.nn), name));
149      assertSame(inCache.get(name.nn), validateNames(TableName.valueOf(name.nnb), name));
150      assertSame(inCache.get(name.nn), validateNames(
151        TableName.valueOf(ByteBuffer.wrap(name.nsb), ByteBuffer.wrap(name.tnb)), name));
152    }
153  }
154
155  private TableName validateNames(TableName expected, Names names) {
156    assertEquals(expected.getNameAsString(), names.nn);
157    assertArrayEquals(expected.getName(), names.nnb);
158    assertEquals(expected.getQualifierAsString(), names.tn);
159    assertArrayEquals(expected.getQualifier(), names.tnb);
160    assertEquals(expected.getNamespaceAsString(), names.ns);
161    assertArrayEquals(expected.getNamespace(), names.nsb);
162    return expected;
163  }
164}