View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.hadoop.hbase.codec.prefixtree.row;
20  
21  import java.io.ByteArrayInputStream;
22  import java.io.ByteArrayOutputStream;
23  import java.io.IOException;
24  import java.nio.ByteBuffer;
25  import java.util.Collection;
26  import java.util.List;
27  
28  import org.apache.hadoop.hbase.Cell;
29  import org.apache.hadoop.hbase.KeyValue;
30  import org.apache.hadoop.hbase.KeyValueUtil;
31  import org.apache.hadoop.hbase.codec.prefixtree.PrefixTreeBlockMeta;
32  import org.apache.hadoop.hbase.codec.prefixtree.decode.PrefixTreeArraySearcher;
33  import org.apache.hadoop.hbase.codec.prefixtree.encode.PrefixTreeEncoder;
34  import org.apache.hadoop.hbase.util.Bytes;
35  import org.junit.Assert;
36  import org.junit.Before;
37  import org.junit.Test;
38  import org.junit.runner.RunWith;
39  import org.junit.runners.Parameterized;
40  import org.junit.runners.Parameterized.Parameters;
41  
42  import com.google.common.collect.Lists;
43  
44  @RunWith(Parameterized.class)
45  public class TestRowEncoder {
46  
47    protected static int BLOCK_START = 7;
48  
49    @Parameters
50    public static Collection<Object[]> parameters() {
51      List<Object[]> parameters = Lists.newArrayList();
52      for (TestRowData testRows : TestRowData.InMemory.getAll()) {
53        parameters.add(new Object[] { testRows });
54      }
55      return parameters;
56    }
57  
58    protected TestRowData rows;
59    protected List<KeyValue> inputKvs;
60    protected boolean includeMemstoreTS = true;
61    protected ByteArrayOutputStream os;
62    protected PrefixTreeEncoder encoder;
63    protected int totalBytes;
64    protected PrefixTreeBlockMeta blockMetaWriter;
65    protected byte[] outputBytes;
66    protected ByteBuffer buffer;
67    protected ByteArrayInputStream is;
68    protected PrefixTreeBlockMeta blockMetaReader;
69    protected byte[] inputBytes;
70    protected PrefixTreeArraySearcher searcher;
71  
72    public TestRowEncoder(TestRowData testRows) {
73      this.rows = testRows;
74    }
75  
76  	@Before
77    public void compile() throws IOException {
78      os = new ByteArrayOutputStream(1 << 20);
79      encoder = new PrefixTreeEncoder(os, includeMemstoreTS);
80  
81      inputKvs = rows.getInputs();
82      for (KeyValue kv : inputKvs) {
83        encoder.write(kv);
84      }
85      encoder.flush();
86      totalBytes = encoder.getTotalBytes();
87      blockMetaWriter = encoder.getBlockMeta();
88      outputBytes = os.toByteArray();
89  
90      // start reading, but save the assertions for @Test methods
91      buffer = ByteBuffer.wrap(outputBytes);
92      blockMetaReader = new PrefixTreeBlockMeta(buffer);
93  
94      searcher = new PrefixTreeArraySearcher(blockMetaReader, blockMetaReader.getRowTreeDepth(),
95          blockMetaReader.getMaxRowLength(), blockMetaReader.getMaxQualifierLength());
96      searcher.initOnBlock(blockMetaReader, outputBytes, includeMemstoreTS);
97    }
98  
99    @Test
100   public void testEncoderOutput() throws IOException {
101     Assert.assertEquals(totalBytes, outputBytes.length);
102     Assert.assertEquals(blockMetaWriter, blockMetaReader);
103   }
104 
105   @Test
106   public void testForwardScanner() {
107     int counter = -1;
108     while (searcher.advance()) {
109       ++counter;
110       KeyValue inputKv = rows.getInputs().get(counter);
111       KeyValue outputKv = KeyValueUtil.copyToNewKeyValue(searcher.current());
112       assertKeyAndValueEqual(inputKv, outputKv);
113     }
114     // assert same number of cells
115     Assert.assertEquals(rows.getInputs().size(), counter + 1);
116   }
117 
118 
119   /**
120    * probably not needed since testReverseScannerWithJitter() below is more thorough
121    */
122   @Test
123   public void testReverseScanner() {
124     searcher.positionAfterLastCell();
125     int counter = -1;
126     while (searcher.previous()) {
127       ++counter;
128       int oppositeIndex = rows.getInputs().size() - counter - 1;
129       KeyValue inputKv = rows.getInputs().get(oppositeIndex);
130       KeyValue outputKv = KeyValueUtil.copyToNewKeyValue(searcher.current());
131       assertKeyAndValueEqual(inputKv, outputKv);
132     }
133     Assert.assertEquals(rows.getInputs().size(), counter + 1);
134   }
135 
136 
137   /**
138    * Exercise the nubCellsRemain variable by calling next+previous.  NubCellsRemain is basically
139    * a special fan index.
140    */
141   @Test
142   public void testReverseScannerWithJitter() {
143     searcher.positionAfterLastCell();
144     int counter = -1;
145     while (true) {
146       boolean foundCell = searcher.previous();
147       if (!foundCell) {
148         break;
149       }
150       ++counter;
151 
152       // a next+previous should cancel out
153       if (!searcher.isAfterLast()) {
154         searcher.advance();
155         searcher.previous();
156       }
157 
158       int oppositeIndex = rows.getInputs().size() - counter - 1;
159       KeyValue inputKv = rows.getInputs().get(oppositeIndex);
160       KeyValue outputKv = KeyValueUtil.copyToNewKeyValue(searcher.current());
161       assertKeyAndValueEqual(inputKv, outputKv);
162     }
163     Assert.assertEquals(rows.getInputs().size(), counter + 1);
164   }
165 
166   @Test
167   public void testIndividualBlockMetaAssertions() {
168     rows.individualBlockMetaAssertions(blockMetaReader);
169   }
170 
171 
172 	/**************** helper **************************/
173 
174   protected void assertKeyAndValueEqual(Cell expected, Cell actual) {
175     // assert keys are equal (doesn't compare values)
176     Assert.assertEquals(expected, actual);
177     if (includeMemstoreTS) {
178       Assert.assertEquals(expected.getMvccVersion(), actual.getMvccVersion());
179     }
180     // assert values equal
181     Assert.assertTrue(Bytes.equals(expected.getValueArray(), expected.getValueOffset(),
182       expected.getValueLength(), actual.getValueArray(), actual.getValueOffset(),
183       actual.getValueLength()));
184   }
185 
186 }