You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@bookkeeper.apache.org by si...@apache.org on 2018/01/24 18:49:00 UTC

[bookkeeper] branch master updated: ISSUE #1041: Adding new testcases

This is an automated email from the ASF dual-hosted git repository.

sijie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/bookkeeper.git


The following commit(s) were added to refs/heads/master by this push:
     new 0ffac5a  ISSUE #1041: Adding new testcases
0ffac5a is described below

commit 0ffac5ac9f7c573eab93a43dae86c1a78e1b61de
Author: cguttapalem <cg...@salesforce.com>
AuthorDate: Wed Jan 24 10:48:53 2018 -0800

    ISSUE #1041: Adding new testcases
    
    Descriptions of the changes in this PR:
    
    - New Testclass for ZeroBuffer
    - New testcases for missing testcoverage in
    SortedLedgerStorage, EntryMemTable and LedgerHandleAdv
    
    Master Issue: #1041
    
    Author: cguttapalem <cg...@salesforce.com>
    Author: Charan Reddy Guttapalem <cg...@salesforce.com>
    
    Reviewers: Sijie Guo <si...@apache.org>
    
    This closes #1042 from reddycharan/missingtestcases, closes #1041
---
 .../bookkeeper/client/BookieWriteLedgerTest.java   | 182 +++++++++++++++++++++
 .../org/apache/bookkeeper/util/TestZeroBuffer.java | 118 +++++++++++++
 2 files changed, 300 insertions(+)

diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/BookieWriteLedgerTest.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/BookieWriteLedgerTest.java
index d3746f4..bae15b8 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/BookieWriteLedgerTest.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/client/BookieWriteLedgerTest.java
@@ -35,13 +35,16 @@ import java.util.Map;
 import java.util.Random;
 import java.util.UUID;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
 
 import org.apache.bookkeeper.client.AsyncCallback.AddCallback;
+import org.apache.bookkeeper.client.BKException.BKLedgerClosedException;
 import org.apache.bookkeeper.client.BookKeeper.DigestType;
 import org.apache.bookkeeper.meta.LongHierarchicalLedgerManagerFactory;
 import org.apache.bookkeeper.net.BookieSocketAddress;
 import org.apache.bookkeeper.test.BookKeeperClusterTestCase;
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.slf4j.Logger;
@@ -94,6 +97,11 @@ public class BookieWriteLedgerTest extends
         String ledgerManagerFactory = "org.apache.bookkeeper.meta.HierarchicalLedgerManagerFactory";
         // set ledger manager
         baseConf.setLedgerManagerFactoryClassName(ledgerManagerFactory);
+        /*
+         * 'testLedgerCreateAdvWithLedgerIdInLoop2' testcase relies on skipListSizeLimit,
+         * so setting it to some small value for making that testcase lite.
+         */
+        baseConf.setSkipListSizeLimit(4 * 1024 * 1024);
         baseClientConf.setLedgerManagerFactoryClassName(ledgerManagerFactory);
     }
 
@@ -344,6 +352,88 @@ public class BookieWriteLedgerTest extends
     }
 
     /*
+     * Verify the functionality of Advanced Ledger which accepts ledgerId as
+     * input and returns LedgerHandleAdv. LedgerHandleAdv takes entryId for
+     * addEntry, and let user manage entryId allocation.
+     * This testcase is mainly added for covering missing code coverage branches
+     * in LedgerHandleAdv
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testLedgerHandleAdvFunctionality() throws Exception {
+        // Create a ledger
+        long ledgerId = 0xABCDEF;
+        lh = bkc.createLedgerAdv(ledgerId, 5, 3, 2, digestType, ledgerPassword, null);
+        numEntriesToWrite = 3;
+
+        ByteBuffer entry = ByteBuffer.allocate(4);
+        entry.putInt(rng.nextInt(maxInt));
+        entry.position(0);
+        entries1.add(entry.array());
+        lh.addEntry(0, entry.array());
+
+        // here asyncAddEntry(final long entryId, final byte[] data, final
+        // AddCallback cb, final Object ctx) method is
+        // called which is not covered in any other testcase
+        entry = ByteBuffer.allocate(4);
+        entry.putInt(rng.nextInt(maxInt));
+        entry.position(0);
+        entries1.add(entry.array());
+        CountDownLatch latch = new CountDownLatch(1);
+        final int[] returnedRC = new int[1];
+        lh.asyncAddEntry(1, entry.array(), new AddCallback() {
+            @Override
+            public void addComplete(int rc, LedgerHandle lh, long entryId, Object ctx) {
+                CountDownLatch latch = (CountDownLatch) ctx;
+                returnedRC[0] = rc;
+                latch.countDown();
+            }
+        }, latch);
+        latch.await();
+        assertTrue("Returned code is expected to be OK", returnedRC[0] == BKException.Code.OK);
+
+        // here addEntry is called with incorrect offset and length
+        entry = ByteBuffer.allocate(4);
+        entry.putInt(rng.nextInt(maxInt));
+        entry.position(0);
+        try {
+            lh.addEntry(2, entry.array(), -3, 9);
+            fail("AddEntry is called with negative offset and incorrect length,"
+                    + "so it is expected to throw RuntimeException/IndexOutOfBoundsException");
+        } catch (RuntimeException exception) {
+            // expected RuntimeException/IndexOutOfBoundsException
+        }
+
+        // here addEntry is called with corrected offset and length and it is
+        // supposed to succeed
+        entry = ByteBuffer.allocate(4);
+        entry.putInt(rng.nextInt(maxInt));
+        entry.position(0);
+        entries1.add(entry.array());
+        lh.addEntry(2, entry.array());
+
+        // LedgerHandle is closed for write
+        lh.close();
+
+        // here addEntry is called even after the close of the LedgerHandle, so
+        // it is expected to throw exception
+        entry = ByteBuffer.allocate(4);
+        entry.putInt(rng.nextInt(maxInt));
+        entry.position(0);
+        entries1.add(entry.array());
+        try {
+            lh.addEntry(3, entry.array());
+            fail("AddEntry is called after the close of LedgerHandle,"
+                    + "so it is expected to throw BKLedgerClosedException");
+        } catch (BKLedgerClosedException exception) {
+        }
+
+        readEntries(lh, entries1);
+        bkc.deleteLedger(ledgerId);
+    }
+
+    /**
      * In a loop create/write/delete the ledger with same ledgerId through
      * the functionality of Advanced Ledger which accepts ledgerId as input.
      *
@@ -393,6 +483,79 @@ public class BookieWriteLedgerTest extends
     }
 
     /**
+     * In a loop create/write/read/delete the ledger with ledgerId through the
+     * functionality of Advanced Ledger which accepts ledgerId as input.
+     * In this testcase (other testcases don't cover these conditions, hence new
+     * testcase is added), we create entries which are greater than
+     * SKIP_LIST_MAX_ALLOC_ENTRY size and tried to addEntries so that the total
+     * length of data written in this testcase is much greater than
+     * SKIP_LIST_SIZE_LIMIT, so that entries will be flushed from EntryMemTable
+     * to persistent storage
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testLedgerCreateAdvWithLedgerIdInLoop2() throws Exception {
+
+        assertTrue("Here we are expecting Bookies are configured to use SortedLedgerStorage",
+                baseConf.getSortedLedgerStorageEnabled());
+
+        long ledgerId;
+        int ledgerCount = 10;
+
+        List<List<byte[]>> entryList = new ArrayList<List<byte[]>>();
+        LedgerHandle[] lhArray = new LedgerHandle[ledgerCount];
+        long skipListSizeLimit = baseConf.getSkipListSizeLimit();
+        int skipListArenaMaxAllocSize = baseConf.getSkipListArenaMaxAllocSize();
+
+        List<byte[]> tmpEntry;
+        for (int lc = 0; lc < ledgerCount; lc++) {
+            tmpEntry = new ArrayList<byte[]>();
+
+            ledgerId = rng.nextLong();
+            ledgerId &= Long.MAX_VALUE;
+            if (!baseConf.getLedgerManagerFactoryClass().equals(LongHierarchicalLedgerManagerFactory.class)) {
+                // since LongHierarchicalLedgerManager supports ledgerIds of
+                // decimal length upto 19 digits but other
+                // LedgerManagers only upto 10 decimals
+                ledgerId %= 9999999999L;
+            }
+
+            LOG.debug("Iteration: {}  LedgerId: {}", lc, ledgerId);
+            lh = bkc.createLedgerAdv(ledgerId, 5, 3, 2, digestType, ledgerPassword, null);
+            lhArray[lc] = lh;
+
+            long ledgerLength = 0;
+            int i = 0;
+            while (ledgerLength < ((4 * skipListSizeLimit) / ledgerCount)) {
+                int length;
+                if (rng.nextBoolean()) {
+                    length = Math.abs(rng.nextInt()) % (skipListArenaMaxAllocSize);
+                } else {
+                    // here we want length to be random no. in the range of skipListArenaMaxAllocSize and
+                    // 4*skipListArenaMaxAllocSize
+                    length = (Math.abs(rng.nextInt()) % (skipListArenaMaxAllocSize * 3)) + skipListArenaMaxAllocSize;
+                }
+                byte[] data = new byte[length];
+                rng.nextBytes(data);
+                tmpEntry.add(data);
+                lh.addEntry(i, data);
+                ledgerLength += length;
+                i++;
+            }
+            entryList.add(tmpEntry);
+        }
+        for (int lc = 0; lc < ledgerCount; lc++) {
+            // Read and verify
+            long lid = lhArray[lc].getId();
+            LOG.debug("readEntries for lc: {} ledgerId: {} ", lc, lhArray[lc].getId());
+            readEntriesAndValidateDataArray(lhArray[lc], entryList.get(lc));
+            lhArray[lc].close();
+            bkc.deleteLedger(lid);
+        }
+    }
+
+    /**
      * Verify asynchronous writing when few bookie failures in last ensemble.
      */
     @Test
@@ -801,6 +964,25 @@ public class BookieWriteLedgerTest extends
         }
     }
 
+    private void readEntriesAndValidateDataArray(LedgerHandle lh, List<byte[]> entries)
+            throws InterruptedException, BKException {
+        ls = lh.readEntries(0, entries.size() - 1);
+        int index = 0;
+        while (ls.hasMoreElements()) {
+            byte[] originalData = entries.get(index++);
+            byte[] receivedData = ls.nextElement().getEntry();
+            LOG.debug("Length of originalData: {}", originalData.length);
+            LOG.debug("Length of receivedData: {}", receivedData.length);
+            assertEquals(
+                    String.format("LedgerID: %d EntryID: %d OriginalDataLength: %d ReceivedDataLength: %d", lh.getId(),
+                            (index - 1), originalData.length, receivedData.length),
+                    originalData.length, receivedData.length);
+            Assert.assertArrayEquals(
+                    String.format("Checking LedgerID: %d EntryID: %d  for equality", lh.getId(), (index - 1)),
+                    originalData, receivedData);
+        }
+    }
+
     @Override
     public void addComplete(int rc, LedgerHandle lh, long entryId, Object ctx) {
         SyncObj x = (SyncObj) ctx;
diff --git a/bookkeeper-server/src/test/java/org/apache/bookkeeper/util/TestZeroBuffer.java b/bookkeeper-server/src/test/java/org/apache/bookkeeper/util/TestZeroBuffer.java
new file mode 100644
index 0000000..cf22416
--- /dev/null
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/util/TestZeroBuffer.java
@@ -0,0 +1,118 @@
+/*
+ *
+ * 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.bookkeeper.util;
+
+import java.nio.ByteBuffer;
+import java.util.Random;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Testcases for ZeroBuffer.
+ */
+public class TestZeroBuffer {
+
+    @Test
+    public void testPut() {
+        ByteBuffer testBuffer;
+        byte[] testBufferArray;
+        Random rand = new Random();
+
+        // Test1 - trying ZeroBuffer.put on small sized TestBuffer
+        testBuffer = ByteBuffer.allocate(5);
+        testBufferArray = testBuffer.array();
+        testBufferArray[4] = 7;
+        Assert.assertFalse("Test1 - It is supposed to contain non-zero byte", isFilledWithZeros(testBufferArray, 0, 5));
+        ZeroBuffer.put(testBuffer);
+        Assert.assertTrue("Test1 - After calling, ZeroBuffer.put There aren't supposed to be non-zero bytes",
+                isFilledWithZeros(testBufferArray, 0, 5));
+
+        // Test2 - trying ZeroBuffer.put on 64*1024 sized TestBuffer
+        testBuffer = ByteBuffer.allocate(64 * 1024);
+        testBufferArray = testBuffer.array();
+        rand.nextBytes(testBufferArray);
+        Assert.assertFalse("Test2 - It is supposed to contain random non-zero bytes",
+                isFilledWithZeros(testBufferArray, 0, 64 * 1024));
+        ZeroBuffer.put(testBuffer);
+        Assert.assertTrue("Test2 - After calling, ZeroBuffer.put There aren't supposed to be non-zero bytes",
+                isFilledWithZeros(testBufferArray, 0, 64 * 1024));
+
+        // Test3 - trying ZeroBuffer.put on portion (64*1024) of large sized
+        // TestBuffer (256*1024)
+        testBuffer = ByteBuffer.allocate(256 * 1024);
+        testBufferArray = testBuffer.array();
+        rand.nextBytes(testBufferArray);
+        Assert.assertFalse("Test3 - It is supposed to contain random non-zero bytes",
+                isFilledWithZeros(testBufferArray, 64 * 1024, 64 * 1024));
+        testBuffer.position(64 * 1024);
+        ZeroBuffer.put(testBuffer, 64 * 1024);
+        Assert.assertTrue(
+                "Test3 - After calling, ZeroBuffer.put There aren't supposed to be non-zero bytes "
+                + "in the particular section", isFilledWithZeros(testBufferArray, 64 * 1024, 64 * 1024));
+        Assert.assertFalse("Test3 - After calling, ZeroBuffer.put other sections shouldnt be touched",
+                isFilledWithZeros(testBufferArray, 0, 64 * 1024));
+        Assert.assertFalse("Test3 - After calling, ZeroBuffer.put other sections shouldnt be touched",
+                isFilledWithZeros(testBufferArray, 128 * 1024, 128 * 1024));
+    }
+
+    @Test
+    public void testReadOnlyBuffer() {
+        ByteBuffer testReadOnlyBuffer;
+        byte[] testBufferArray;
+
+        // Test1 - trying ZeroBuffer.readOnlyBuffer for small size
+        testReadOnlyBuffer = ZeroBuffer.readOnlyBuffer(5);
+        Assert.assertTrue(
+                "Test1 - ReadOnlyBuffer should have remaining 5 bytes but it has " + testReadOnlyBuffer.remaining(),
+                testReadOnlyBuffer.remaining() == 5);
+        testBufferArray = new byte[5];
+        testReadOnlyBuffer.get(testBufferArray);
+        Assert.assertTrue("Test1 - supposed to contain only zero bytes", isFilledWithZeros(testBufferArray, 0, 5));
+
+        // Test2 - trying ZeroBuffer.readOnlyBuffer for 64*1024
+        testReadOnlyBuffer = ZeroBuffer.readOnlyBuffer(64 * 1024);
+        Assert.assertTrue("Test2 - ReadOnlyBuffer should have remaining 64*1024 bytes but it has "
+                + testReadOnlyBuffer.remaining(), testReadOnlyBuffer.remaining() == 64 * 1024);
+        testBufferArray = new byte[64 * 1024];
+        testReadOnlyBuffer.get(testBufferArray);
+        Assert.assertTrue("Test2 - supposed to contain only zero bytes",
+                isFilledWithZeros(testBufferArray, 0, 64 * 1024));
+
+        // Test3 - trying ZeroBuffer.readOnlyBuffer for > 64*1024
+        testReadOnlyBuffer = ZeroBuffer.readOnlyBuffer(128 * 1024);
+        Assert.assertTrue("Test3 - ReadOnlyBuffer should have remaining 128*1024 bytes but it has "
+                + testReadOnlyBuffer.remaining(), testReadOnlyBuffer.remaining() == 128 * 1024);
+        testBufferArray = new byte[128 * 1024];
+        testReadOnlyBuffer.get(testBufferArray);
+        Assert.assertTrue("Test3 - supposed to contain only zero bytes",
+                isFilledWithZeros(testBufferArray, 0, 128 * 1024));
+    }
+
+    boolean isFilledWithZeros(byte[] byteArray, int start, int length) {
+        for (int i = start; i < (start + length); i++) {
+            if (byteArray[i] != 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+}

-- 
To stop receiving notification emails like this one, please contact
sijie@apache.org.