001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with this
004 * work for additional information regarding copyright ownership. The ASF
005 * licenses this file to you under the Apache License, Version 2.0 (the
006 * "License"); you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014 * License for the specific language governing permissions and limitations
015 * under the License.
016 */
017package org.apache.hadoop.hbase;
018
019import java.io.IOException;
020import java.util.Arrays;
021import java.util.HashSet;
022import java.util.Set;
023import java.util.Collections;
024import org.apache.hadoop.hbase.client.Durability;
025import org.apache.hadoop.hbase.client.Put;
026import org.apache.hadoop.hbase.client.Table;
027import org.apache.hadoop.hbase.regionserver.Region;
028import org.apache.hadoop.hbase.regionserver.RegionAsTable;
029import org.apache.hadoop.hbase.util.Bytes;
030
031/**
032 * Similar to {@link HConstants} but for tests. Also provides some simple static utility functions
033 * to generate test data.
034 */
035public class HTestConst {
036
037  private HTestConst() {
038  }
039
040  public static final String DEFAULT_TABLE_STR = "MyTestTable";
041  public static final byte[] DEFAULT_TABLE_BYTES = Bytes.toBytes(DEFAULT_TABLE_STR);
042  public static final TableName DEFAULT_TABLE = TableName.valueOf(DEFAULT_TABLE_BYTES);
043
044  public static final String DEFAULT_CF_STR = "MyDefaultCF";
045  public static final byte[] DEFAULT_CF_BYTES = Bytes.toBytes(DEFAULT_CF_STR);
046
047  public static final Set<String> DEFAULT_CF_STR_SET =
048    Collections.unmodifiableSet(new HashSet<>(Arrays.asList(new String[] { DEFAULT_CF_STR })));
049
050  public static final String DEFAULT_ROW_STR = "MyTestRow";
051  public static final byte[] DEFAULT_ROW_BYTES = Bytes.toBytes(DEFAULT_ROW_STR);
052
053  public static final String DEFAULT_QUALIFIER_STR = "MyColumnQualifier";
054  public static final byte[] DEFAULT_QUALIFIER_BYTES = Bytes.toBytes(DEFAULT_QUALIFIER_STR);
055
056  public static String DEFAULT_VALUE_STR = "MyTestValue";
057  public static byte[] DEFAULT_VALUE_BYTES = Bytes.toBytes(DEFAULT_VALUE_STR);
058
059  private static final char FIRST_CHAR = 'a';
060  private static final char LAST_CHAR = 'z';
061  private static final byte[] START_KEY_BYTES = { FIRST_CHAR, FIRST_CHAR, FIRST_CHAR };
062
063  /**
064   * Generate the given number of unique byte sequences by appending numeric suffixes (ASCII
065   * representations of decimal numbers).
066   */
067  public static byte[][] makeNAscii(byte[] base, int n) {
068    byte[][] ret = new byte[n][];
069    for (int i = 0; i < n; i++) {
070      byte[] tail = Bytes.toBytes(Integer.toString(i));
071      ret[i] = Bytes.add(base, tail);
072    }
073    return ret;
074  }
075
076  /**
077   * Add content to region <code>r</code> on the passed column <code>column</code>. Adds data of the
078   * from 'aaa', 'aab', etc where key and value are the same.
079   * @return count of what we added.
080   */
081  public static long addContent(final Region r, final byte[] columnFamily, final byte[] column)
082    throws IOException {
083    byte[] startKey = r.getRegionInfo().getStartKey();
084    byte[] endKey = r.getRegionInfo().getEndKey();
085    byte[] startKeyBytes = startKey;
086    if (startKeyBytes == null || startKeyBytes.length == 0) {
087      startKeyBytes = START_KEY_BYTES;
088    }
089    return addContent(new RegionAsTable(r), Bytes.toString(columnFamily), Bytes.toString(column),
090      startKeyBytes, endKey, -1);
091  }
092
093  public static long addContent(final Region r, final byte[] columnFamily) throws IOException {
094    return addContent(r, columnFamily, null);
095  }
096
097  /**
098   * Add content to region <code>r</code> on the passed column <code>column</code>. Adds data of the
099   * from 'aaa', 'aab', etc where key and value are the same.
100   * @return count of what we added.
101   */
102  public static long addContent(Table updater, String columnFamily) throws IOException {
103    return addContent(updater, columnFamily, START_KEY_BYTES, null);
104  }
105
106  public static long addContent(Table updater, String family, String column) throws IOException {
107    return addContent(updater, family, column, START_KEY_BYTES, null);
108  }
109
110  /**
111   * Add content to region <code>r</code> on the passed column <code>column</code>. Adds data of the
112   * from 'aaa', 'aab', etc where key and value are the same.
113   * @return count of what we added.
114   */
115  public static long addContent(Table updater, String columnFamily, byte[] startKeyBytes,
116    byte[] endKey) throws IOException {
117    return addContent(updater, columnFamily, null, startKeyBytes, endKey, -1);
118  }
119
120  public static long addContent(Table updater, String family, String column, byte[] startKeyBytes,
121    byte[] endKey) throws IOException {
122    return addContent(updater, family, column, startKeyBytes, endKey, -1);
123  }
124
125  /**
126   * Add content to region <code>r</code> on the passed column <code>column</code>. Adds data of the
127   * from 'aaa', 'aab', etc where key and value are the same.
128   * @return count of what we added.
129   */
130  public static long addContent(Table updater, String columnFamily, String column,
131    byte[] startKeyBytes, byte[] endKey, long ts) throws IOException {
132    long count = 0;
133    // Add rows of three characters. The first character starts with the
134    // 'a' character and runs up to 'z'. Per first character, we run the
135    // second character over same range. And same for the third so rows
136    // (and values) look like this: 'aaa', 'aab', 'aac', etc.
137    char secondCharStart = (char) startKeyBytes[1];
138    char thirdCharStart = (char) startKeyBytes[2];
139    EXIT: for (char c = (char) startKeyBytes[0]; c <= LAST_CHAR; c++) {
140      for (char d = secondCharStart; d <= LAST_CHAR; d++) {
141        for (char e = thirdCharStart; e <= LAST_CHAR; e++) {
142          byte[] t = new byte[] { (byte) c, (byte) d, (byte) e };
143          if (endKey != null && endKey.length > 0 && Bytes.compareTo(endKey, t) <= 0) {
144            break EXIT;
145          }
146          Put put;
147          if (ts != -1) {
148            put = new Put(t, ts);
149          } else {
150            put = new Put(t);
151          }
152          StringBuilder sb = new StringBuilder();
153          if (column != null && column.contains(":")) {
154            sb.append(column);
155          } else {
156            if (columnFamily != null) {
157              sb.append(columnFamily);
158              if (!columnFamily.endsWith(":")) {
159                sb.append(":");
160              }
161              if (column != null) {
162                sb.append(column);
163              }
164            }
165          }
166          byte[][] split = CellUtil.parseColumn(Bytes.toBytes(sb.toString()));
167          if (split.length == 1) {
168            byte[] qualifier = new byte[0];
169            put.addColumn(split[0], qualifier, t);
170          } else {
171            put.addColumn(split[0], split[1], t);
172          }
173          put.setDurability(Durability.SKIP_WAL);
174          updater.put(put);
175          count++;
176        }
177        // Set start character back to FIRST_CHAR after we've done first loop.
178        thirdCharStart = FIRST_CHAR;
179      }
180      secondCharStart = FIRST_CHAR;
181    }
182    return count;
183  }
184}