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.mapreduce;
019
020import java.io.IOException;
021import javax.validation.constraints.Null;
022import org.apache.hadoop.conf.Configuration;
023import org.apache.hadoop.hbase.HBaseClassTestRule;
024import org.apache.hadoop.hbase.HBaseTestingUtil;
025import org.apache.hadoop.hbase.TableName;
026import org.apache.hadoop.hbase.client.Delete;
027import org.apache.hadoop.hbase.client.Durability;
028import org.apache.hadoop.hbase.client.Mutation;
029import org.apache.hadoop.hbase.client.Put;
030import org.apache.hadoop.hbase.testclassification.MediumTests;
031import org.apache.hadoop.hbase.util.Bytes;
032import org.apache.hadoop.mapreduce.RecordWriter;
033import org.apache.hadoop.mapreduce.TaskAttemptContext;
034import org.junit.After;
035import org.junit.AfterClass;
036import org.junit.Assert;
037import org.junit.BeforeClass;
038import org.junit.ClassRule;
039import org.junit.Test;
040import org.junit.experimental.categories.Category;
041import org.mockito.Mockito;
042
043/**
044 * Simple Tests to check whether the durability of the Mutation is changed or not, for
045 * {@link TableOutputFormat} if {@link TableOutputFormat#WAL_PROPERTY} is set to false.
046 */
047@Category(MediumTests.class)
048public class TestTableOutputFormat {
049  @ClassRule
050  public static final HBaseClassTestRule CLASS_RULE =
051    HBaseClassTestRule.forClass(TestTableOutputFormat.class);
052
053  private static final HBaseTestingUtil util = new HBaseTestingUtil();
054  private static final TableName TABLE_NAME = TableName.valueOf("TEST_TABLE");
055  private static final byte[] columnFamily = Bytes.toBytes("f");
056  private static Configuration conf;
057  private static RecordWriter<Null, Mutation> writer;
058  private static TaskAttemptContext context;
059  private static TableOutputFormat<Null> tableOutputFormat;
060
061  @BeforeClass
062  public static void setUp() throws Exception {
063    util.startMiniCluster();
064    util.createTable(TABLE_NAME, columnFamily);
065
066    conf = new Configuration(util.getConfiguration());
067    context = Mockito.mock(TaskAttemptContext.class);
068    tableOutputFormat = new TableOutputFormat<>();
069    conf.set(TableOutputFormat.OUTPUT_TABLE, "TEST_TABLE");
070  }
071
072  @AfterClass
073  public static void tearDown() throws Exception {
074    util.shutdownMiniCluster();
075  }
076
077  @After
078  public void close() throws IOException, InterruptedException {
079    if (writer != null && context != null) {
080      writer.close(context);
081    }
082  }
083
084  @Test
085  public void testTableOutputFormatWhenWalIsOFFForPut() throws IOException, InterruptedException {
086    // setting up the configuration for the TableOutputFormat, with writing to the WAL off.
087    conf.setBoolean(TableOutputFormat.WAL_PROPERTY, TableOutputFormat.WAL_OFF);
088    tableOutputFormat.setConf(conf);
089
090    writer = tableOutputFormat.getRecordWriter(context);
091
092    // creating mutation of the type put
093    Put put = new Put("row1".getBytes());
094    put.addColumn(columnFamily, Bytes.toBytes("aa"), Bytes.toBytes("value"));
095
096    // verifying whether durability of mutation is USE_DEFAULT or not, before commiting write.
097    Assert.assertEquals("Durability of the mutation should be USE_DEFAULT", Durability.USE_DEFAULT,
098      put.getDurability());
099
100    writer.write(null, put);
101
102    // verifying whether durability of mutation got changed to the SKIP_WAL or not.
103    Assert.assertEquals("Durability of the mutation should be SKIP_WAL", Durability.SKIP_WAL,
104      put.getDurability());
105  }
106
107  @Test
108  public void testTableOutputFormatWhenWalIsOFFForDelete()
109    throws IOException, InterruptedException {
110    // setting up the configuration for the TableOutputFormat, with writing to the WAL off.
111    conf.setBoolean(TableOutputFormat.WAL_PROPERTY, TableOutputFormat.WAL_OFF);
112    tableOutputFormat.setConf(conf);
113
114    writer = tableOutputFormat.getRecordWriter(context);
115
116    // creating mutation of the type delete
117    Delete delete = new Delete("row2".getBytes());
118    delete.addColumn(columnFamily, Bytes.toBytes("aa"));
119
120    // verifying whether durability of mutation is USE_DEFAULT or not, before commiting write.
121    Assert.assertEquals("Durability of the mutation should be USE_DEFAULT", Durability.USE_DEFAULT,
122      delete.getDurability());
123
124    writer.write(null, delete);
125
126    // verifying whether durability of mutation got changed from USE_DEFAULT to the SKIP_WAL or not.
127    Assert.assertEquals("Durability of the mutation should be SKIP_WAL", Durability.SKIP_WAL,
128      delete.getDurability());
129  }
130}