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.util; 019 020import static org.hamcrest.MatcherAssert.assertThat; 021import static org.hamcrest.Matchers.startsWith; 022import static org.junit.Assert.assertEquals; 023import static org.junit.Assert.assertNull; 024import static org.junit.Assert.assertThrows; 025 026import java.io.IOException; 027import org.apache.hadoop.fs.FSDataInputStream; 028import org.apache.hadoop.fs.FSDataOutputStream; 029import org.apache.hadoop.fs.FileSystem; 030import org.apache.hadoop.fs.Path; 031import org.apache.hadoop.hbase.HBaseClassTestRule; 032import org.apache.hadoop.hbase.HBaseCommonTestingUtil; 033import org.apache.hadoop.hbase.testclassification.MiscTests; 034import org.apache.hadoop.hbase.testclassification.SmallTests; 035import org.junit.AfterClass; 036import org.junit.Before; 037import org.junit.BeforeClass; 038import org.junit.ClassRule; 039import org.junit.Rule; 040import org.junit.Test; 041import org.junit.experimental.categories.Category; 042import org.junit.rules.TestName; 043 044import org.apache.hbase.thirdparty.com.google.common.io.ByteStreams; 045 046@Category({ MiscTests.class, SmallTests.class }) 047public class TestRotateFile { 048 049 @ClassRule 050 public static final HBaseClassTestRule CLASS_RULE = 051 HBaseClassTestRule.forClass(TestRotateFile.class); 052 053 private static HBaseCommonTestingUtil UTIL = new HBaseCommonTestingUtil(); 054 055 private static FileSystem FS; 056 057 private Path dir; 058 059 private RotateFile rotateFile; 060 061 @Rule 062 public final TestName name = new TestName(); 063 064 @BeforeClass 065 public static void setUpBeforeClass() throws IOException { 066 FS = FileSystem.get(UTIL.getConfiguration()); 067 } 068 069 @AfterClass 070 public static void tearDownAfterClass() { 071 UTIL.cleanupTestDir(); 072 } 073 074 @Before 075 public void setUp() throws IOException { 076 dir = UTIL.getDataTestDir(name.getMethodName()); 077 if (!FS.mkdirs(dir)) { 078 throw new IOException("Can not create dir " + dir); 079 } 080 rotateFile = new RotateFile(FS, dir, name.getMethodName(), 1024); 081 assertNull(rotateFile.read()); 082 } 083 084 @Test 085 public void testSimpleReadWrite() throws IOException { 086 for (int i = 0; i < 10; i++) { 087 rotateFile.write(Bytes.toBytes(i)); 088 assertEquals(i, Bytes.toInt(rotateFile.read())); 089 } 090 rotateFile.delete(); 091 assertNull(rotateFile.read()); 092 } 093 094 @Test 095 public void testCompareTimestamp() throws IOException { 096 long now = EnvironmentEdgeManager.currentTime(); 097 rotateFile.write(Bytes.toBytes(10)); 098 Path file = FS.listStatus(dir)[0].getPath(); 099 rotateFile.write(Bytes.toBytes(100)); 100 101 // put a fake file with a less timestamp there 102 RotateFile.write(FS, file, now - 1, Bytes.toBytes(10)); 103 assertEquals(100, Bytes.toInt(rotateFile.read())); 104 105 // put a fake file with a greater timestamp there 106 RotateFile.write(FS, file, EnvironmentEdgeManager.currentTime() + 100, Bytes.toBytes(10)); 107 assertEquals(10, Bytes.toInt(rotateFile.read())); 108 } 109 110 @Test 111 public void testMaxFileSize() throws IOException { 112 assertThrows(IOException.class, () -> rotateFile.write(new byte[1025])); 113 // put a file greater than max file size 114 rotateFile.write(Bytes.toBytes(10)); 115 Path file = FS.listStatus(dir)[0].getPath(); 116 RotateFile.write(FS, file, EnvironmentEdgeManager.currentTime(), new byte[1025]); 117 assertThrows(IOException.class, () -> rotateFile.read()); 118 } 119 120 @Test 121 public void testNotEnoughData() throws IOException { 122 rotateFile.write(Bytes.toBytes(10)); 123 assertEquals(10, Bytes.toInt(rotateFile.read())); 124 // remove the last byte 125 Path file = FS.listStatus(dir)[0].getPath(); 126 byte[] data; 127 try (FSDataInputStream in = FS.open(file)) { 128 data = ByteStreams.toByteArray(in); 129 } 130 try (FSDataOutputStream out = FS.create(file, true)) { 131 out.write(data, 0, data.length - 1); 132 } 133 // should hit EOF so read nothing 134 assertNull(rotateFile.read()); 135 } 136 137 @Test 138 public void testChecksumMismatch() throws IOException { 139 rotateFile.write(Bytes.toBytes(10)); 140 assertEquals(10, Bytes.toInt(rotateFile.read())); 141 // mess up one byte 142 Path file = FS.listStatus(dir)[0].getPath(); 143 byte[] data; 144 try (FSDataInputStream in = FS.open(file)) { 145 data = ByteStreams.toByteArray(in); 146 } 147 data[4]++; 148 try (FSDataOutputStream out = FS.create(file, true)) { 149 out.write(data, 0, data.length); 150 } 151 // should get checksum mismatch 152 IOException error = assertThrows(IOException.class, () -> rotateFile.read()); 153 assertThat(error.getMessage(), startsWith("Checksum mismatch")); 154 } 155}