/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.hdfs; import java.util.HashMap; import java.util.Random; import junit.framework.TestCase; import org.apache.hadoop.util.CrcConcat; import org.apache.hadoop.util.DataChecksum; import org.junit.Before; import org.junit.Test; public class TestCrcConcat { byte[] data = new byte[2 * 1024 * 1024 + 888]; DataChecksum checksum; HashMap<String, Integer> checksumMap; @Before public void setUpClass() throws Exception { checksum = DataChecksum.newDataChecksum( DataChecksum.CHECKSUM_CRC32, 4); checksumMap = new HashMap<String, Integer>(); } /** * Get checksum of data array, from offset with length. * Use a cache to avoid to calculated repeatly. * @param off * @param length * @return */ private int getChecksum(int off, int length) { Integer co = checksumMap.get("" + off + ":" + length); if (co == null) { checksum.reset(); checksum.update(data, off, length); int newC = (int) checksum.getValue(); checksumMap.put("" + off + ":" + length, newC); return newC; } else { return co.intValue(); } } private void verifyCat(int off, int len1, int len2) { int crc1 = getChecksum(off, len1); int crc2 = getChecksum(off + len1, len2); int combineCrc = getChecksum(off, len1 + len2); int combineByCrcConcat = CrcConcat.concatCrc(crc1, crc2, len2); TestCase.assertEquals(combineCrc, combineByCrcConcat); } @Test public void testConcatCrc() throws Exception { Random random = new Random(1); random.nextBytes(data); // small remain verifyCat(0, 4, 1); verifyCat(0, 4, 2); verifyCat(0, 4, 3); verifyCat(0, 4, 4); verifyCat(0, 6, 1); verifyCat(0, 6, 3); verifyCat(0, 1, 4); verifyCat(0, 3, 6); verifyCat(0, 512, 130); verifyCat(0, 513, 132); verifyCat(0, 513, 131); verifyCat(0, 513, 130); verifyCat(0, 513, 129); verifyCat(0, 513, 128); verifyCat(0, 131, 194); verifyCat(0, 515, 515); // byte level verifyCat(0, 512, 512); verifyCat(0, 1024, 512); verifyCat(0, 1536, 512); verifyCat(0, 1024, 1024); verifyCat(0, 1024, 1277); verifyCat(0, 2048, 253); // MB byte level verifyCat(0, 1024 * 1024, 1024 * 1024); verifyCat(0, 2 * 1024 * 1024, 888); verifyCat(0, 1536, 512); verifyCat(0, 1024, 1024); verifyCat(0, 1024, 1277); verifyCat(0, 2048, 253); } @Test public void testConcatCrcRandom() throws Exception { checksumMap.clear(); Random random = new Random(System.currentTimeMillis()); random.nextBytes(data); // small remain verifyCat(0, 4, 1); verifyCat(0, 4, 2); verifyCat(0, 4, 3); verifyCat(0, 4, 4); verifyCat(0, 6, 1); verifyCat(0, 6, 3); verifyCat(0, 1, 4); verifyCat(0, 3, 6); verifyCat(0, 512, 130); verifyCat(0, 513, 132); verifyCat(0, 513, 131); verifyCat(0, 513, 130); verifyCat(0, 513, 129); verifyCat(0, 513, 128); verifyCat(0, 131, 194); verifyCat(0, 515, 515); // byte level verifyCat(0, 512, 512); verifyCat(0, 1024, 512); verifyCat(0, 1536, 512); verifyCat(0, 1024, 1024); verifyCat(0, 1024, 1277); verifyCat(0, 2048, 253); // MB byte level verifyCat(0, 1024 * 1024, 1024 * 1024); verifyCat(0, 2 * 1024 * 1024, 888); verifyCat(0, 1536, 512); verifyCat(0, 1024, 1024); verifyCat(0, 1024, 1277); verifyCat(0, 2048, 253); } /** * Calculate CRC checksum for number bytes from the random generator * @param random * @param numBytes * @return */ private int getChecksum(Random random, int numBytes) { byte[] data = new byte[1024]; checksum.reset(); for (int i = 0; i < numBytes / 1024; i++) { random.nextBytes(data); checksum.update(data, 0, 1024); } if (numBytes % 1024 != 0) { byte[] data1 = new byte[numBytes % 1024]; random.nextBytes(data1); checksum.update(data1, 0, numBytes % 1024); } return (int) checksum.getValue(); } @Test public void testConcatCrcBlocks() throws Exception { int lastBlockLength = 38888889; Random random; // Verify concatenating two 256MB blocks random = new Random(1); int checksumb1 = getChecksum(random, 256 * 1024 * 1024); int checksumb2 = getChecksum(random, 256 * 1024 * 1024); int checksumb3 = getChecksum(random, lastBlockLength); // Verify concatenating two blocks' CRC random = new Random(1); int checksum2b = getChecksum(random, 2 * 256 * 1024 * 1024);; int concatedChcksum2b = CrcConcat.concatCrc(checksumb1, checksumb2, 256 * 1024 * 1024); TestCase.assertEquals(checksum2b, concatedChcksum2b); // Verify full CRC. random = new Random(1); int checksum_all = getChecksum(random, 2 * 256 * 1024 * 1024 + lastBlockLength); int concatedChcksum_all = CrcConcat.concatCrc(checksum2b, checksumb3, lastBlockLength); TestCase.assertEquals(checksum_all, concatedChcksum_all); } }