You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by kl...@apache.org on 2017/03/16 21:07:03 UTC

[3/3] geode git commit: GEODE-2648: always move deleted files to dirOfDeletedFiles

GEODE-2648: always move deleted files to dirOfDeletedFiles


Project: http://git-wip-us.apache.org/repos/asf/geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/geode/commit/d01db82c
Tree: http://git-wip-us.apache.org/repos/asf/geode/tree/d01db82c
Diff: http://git-wip-us.apache.org/repos/asf/geode/diff/d01db82c

Branch: refs/heads/feature/GEODE-2648
Commit: d01db82c2dbe9b380c060121f345e0470331e5c9
Parents: 41e14b5
Author: Kirk Lund <kl...@apache.org>
Authored: Mon Mar 13 16:02:53 2017 -0700
Committer: Kirk Lund <kl...@apache.org>
Committed: Thu Mar 16 13:54:44 2017 -0700

----------------------------------------------------------------------
 .../apache/geode/internal/util/ArrayUtils.java  |  27 +++
 .../DiskSpaceLimitIntegrationTest.java          |  50 +++--
 .../internal/util/ArrayUtilsJUnitTest.java      | 176 ---------------
 .../geode/internal/util/ArrayUtilsTest.java     | 219 +++++++++++++++++++
 4 files changed, 274 insertions(+), 198 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/geode/blob/d01db82c/geode-core/src/main/java/org/apache/geode/internal/util/ArrayUtils.java
----------------------------------------------------------------------
diff --git a/geode-core/src/main/java/org/apache/geode/internal/util/ArrayUtils.java b/geode-core/src/main/java/org/apache/geode/internal/util/ArrayUtils.java
index 3459e16..6f1c7cc 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/util/ArrayUtils.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/util/ArrayUtils.java
@@ -15,7 +15,12 @@
 
 package org.apache.geode.internal.util;
 
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.RandomAccess;
 
 import org.apache.geode.internal.lang.StringUtils;
 import org.apache.geode.internal.offheap.annotations.Unretained;
@@ -361,4 +366,26 @@ public abstract class ArrayUtils {
     }
     return array;
   }
+
+  /**
+   * Use this instead of Arrays.asList(T... array) when you need a modifiable List.
+   *
+   * Returns a modifiable list containing the elements of the specified array.
+   *
+   * <p>
+   * Example usage:
+   * 
+   * <pre>
+   * List&lt;String&gt; stooges = Arrays.asList("Larry", "Moe", "Curly");
+   * stooges.remove("Curly");
+   * </pre>
+   *
+   * @param <T> the class of the objects in the array
+   * @param array the array of elements to be added to the list
+   * @return a list containing the elements of the specified array
+   */
+  public static <T> List<T> asList(T... array) {
+    return new ArrayList<>(Arrays.asList(array));
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/geode/blob/d01db82c/geode-core/src/test/java/org/apache/geode/internal/statistics/DiskSpaceLimitIntegrationTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/statistics/DiskSpaceLimitIntegrationTest.java b/geode-core/src/test/java/org/apache/geode/internal/statistics/DiskSpaceLimitIntegrationTest.java
index 5d94fa0..c46817f 100644
--- a/geode-core/src/test/java/org/apache/geode/internal/statistics/DiskSpaceLimitIntegrationTest.java
+++ b/geode-core/src/test/java/org/apache/geode/internal/statistics/DiskSpaceLimitIntegrationTest.java
@@ -28,6 +28,7 @@ import org.apache.geode.StatisticsType;
 import org.apache.geode.internal.NanoTimer;
 import org.apache.geode.internal.io.MainWithChildrenRollingFileHandler;
 import org.apache.geode.internal.io.RollingFileHandler;
+import org.apache.geode.internal.util.ArrayUtils;
 import org.apache.geode.test.junit.categories.IntegrationTest;
 import org.junit.After;
 import org.junit.Before;
@@ -41,7 +42,6 @@ import java.io.File;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.concurrent.TimeoutException;
 
@@ -65,7 +65,6 @@ public class DiskSpaceLimitIntegrationTest {
   private Statistics statistics;
 
   private RollingFileHandler testRollingFileHandler;
-  private MainWithChildrenRollingFileHandler mainWithChildrenRollingFileHandler;
 
   private SampleCollector sampleCollector;
   private StatArchiveHandlerConfig config;
@@ -83,6 +82,7 @@ public class DiskSpaceLimitIntegrationTest {
   @Before
   public void setUp() throws Exception {
     this.dir = this.temporaryFolder.getRoot();
+    this.dirOfDeletedFiles = this.temporaryFolder.newFolder("deleted");
 
     this.name = this.testName.getMethodName();
 
@@ -108,13 +108,18 @@ public class DiskSpaceLimitIntegrationTest {
     when(this.config.getProductDescription()).thenReturn(this.testName.getMethodName());
 
     this.testRollingFileHandler = new TestableRollingFileHandler();
-    this.mainWithChildrenRollingFileHandler = new MainWithChildrenRollingFileHandler();
 
     this.sampleCollector = new SampleCollector(sampler);
 
     this.initTimeStamp = NanoTimer.getTime();
     this.timer.reset();
     this.nanosTimeStamp = this.timer.getLastResetTime() - getNanoRate();
+
+    preConditions();
+  }
+
+  private void preConditions() throws Exception {
+    validateNumberFiles(0);
   }
 
   @After
@@ -124,7 +129,6 @@ public class DiskSpaceLimitIntegrationTest {
 
   @Test
   public void zeroKeepsAllFiles() throws Exception {
-    this.dirOfDeletedFiles = this.temporaryFolder.newFolder("deleted");
     this.sampleCollector.initialize(this.config, this.initTimeStamp, this.testRollingFileHandler);
 
     when(this.config.getArchiveDiskSpaceLimit()).thenReturn(0L);
@@ -136,7 +140,6 @@ public class DiskSpaceLimitIntegrationTest {
 
   @Test
   public void aboveZeroDeletesOldestFile() throws Exception {
-    this.dirOfDeletedFiles = this.temporaryFolder.newFolder("deleted");
     this.sampleCollector.initialize(this.config, this.initTimeStamp, this.testRollingFileHandler);
 
     when(this.config.getArchiveDiskSpaceLimit()).thenReturn(DISK_SPACE_LIMIT);
@@ -161,16 +164,14 @@ public class DiskSpaceLimitIntegrationTest {
 
   @Test
   public void aboveZeroDeletesPreviousFiles() throws Exception {
-    assertThat(numberOfFiles(this.dir)).as("Unexpected files: " + listFiles(this.dir)).isEqualTo(0);
-
     int oldMainId = 1;
     int newMainId = 2;
 
     int numberOfPreviousFiles = 100;
     int numberOfLines = 100;
     createPreviousFiles(oldMainId, numberOfPreviousFiles, numberOfLines);
-    assertThat(numberOfFiles(this.dir)).as("Missing files: " + listFiles(this.dir))
-        .isEqualTo(numberOfPreviousFiles);
+
+    validateNumberFiles(numberOfPreviousFiles);
 
     for (int childId = 1; childId <= numberOfPreviousFiles; childId++) {
       assertThat(archiveFile(oldMainId, childId)).exists();
@@ -186,8 +187,7 @@ public class DiskSpaceLimitIntegrationTest {
     when(this.config.getArchiveDiskSpaceLimit())
         .thenReturn(sizeOfDirectory(this.dir) / numberOfPreviousFiles);
 
-    this.sampleCollector.initialize(this.config, this.initTimeStamp,
-        this.mainWithChildrenRollingFileHandler);
+    this.sampleCollector.initialize(this.config, this.initTimeStamp, this.testRollingFileHandler);
 
     assertThat(archiveFile()).exists().hasParent(this.dir);
     assertThat(markerFile(newMainId)).exists().hasParent(this.dir).hasBinaryContent(new byte[0]);
@@ -199,8 +199,7 @@ public class DiskSpaceLimitIntegrationTest {
     sampleUntilFileExists(archiveFile(newMainId, 1));
     assertThat(archiveFile(newMainId, 1)).exists();
 
-    // this might be a brittle assertion... ok to delete if following for-block-assertion passes
-    assertThat(numberOfFiles(this.dir)).as("Unexpected files: " + listFiles(this.dir)).isEqualTo(2);
+    validateNumberFiles(2);
 
     for (int childId = 1; childId <= numberOfPreviousFiles; childId++) {
       assertThat(archiveFile(oldMainId, childId)).doesNotExist();
@@ -213,16 +212,14 @@ public class DiskSpaceLimitIntegrationTest {
     this.archiveFileName = new File(this.dir, this.name + ".gfs").getAbsolutePath();
     when(this.config.getArchiveFileName()).thenReturn(new File(this.archiveFileName));
 
-    assertThat(numberOfFiles(this.dir)).as("Unexpected files: " + listFiles(this.dir)).isEqualTo(0);
-
     int oldMainId = 1;
     int newMainId = 2;
 
     int numberOfPreviousFiles = 100;
     int numberOfLines = 100;
     createPreviousFiles(oldMainId, numberOfPreviousFiles, numberOfLines);
-    assertThat(numberOfFiles(this.dir)).as("Missing files: " + listFiles(this.dir))
-        .isEqualTo(numberOfPreviousFiles);
+
+    validateNumberFiles(numberOfPreviousFiles);
 
     for (int childId = 1; childId <= numberOfPreviousFiles; childId++) {
       assertThat(archiveFile(oldMainId, childId)).exists();
@@ -238,8 +235,7 @@ public class DiskSpaceLimitIntegrationTest {
     when(this.config.getArchiveDiskSpaceLimit())
         .thenReturn(sizeOfDirectory(this.dir) / numberOfPreviousFiles);
 
-    this.sampleCollector.initialize(this.config, this.initTimeStamp,
-        this.mainWithChildrenRollingFileHandler);
+    this.sampleCollector.initialize(this.config, this.initTimeStamp, this.testRollingFileHandler);
 
     assertThat(archiveFile()).exists().hasParent(this.dir);
     assertThat(markerFile(newMainId)).exists().hasParent(this.dir).hasBinaryContent(new byte[0]);
@@ -252,13 +248,21 @@ public class DiskSpaceLimitIntegrationTest {
     assertThat(archiveFile(newMainId, 1)).exists();
 
     // this might be a brittle assertion... ok to delete if following for-block-assertion passes
-    assertThat(numberOfFiles(this.dir)).as("Unexpected files: " + listFiles(this.dir)).isEqualTo(2);
+    validateNumberFiles(2);
 
     for (int childId = 1; childId <= numberOfPreviousFiles; childId++) {
       assertThat(archiveFile(oldMainId, childId)).doesNotExist();
     }
   }
 
+  /**
+   * Validates number of files under this.dir while ignoring this.dirOfDeletedFiles.
+   */
+  private void validateNumberFiles(final int expected) {
+    assertThat(numberOfFiles(this.dir)).as("Unexpected files: " + listFiles(this.dir))
+        .isEqualTo(expected);
+  }
+
   private void sampleNumberOfTimes(final int value) throws InterruptedException {
     long minutes = 1;
     long timeout = System.nanoTime() + MINUTES.toNanos(minutes);
@@ -389,11 +393,13 @@ public class DiskSpaceLimitIntegrationTest {
   }
 
   private List<File> listFiles(final File dir) {
-    return Arrays.asList(dir.listFiles());
+    List<File> files = ArrayUtils.asList(dir.listFiles());
+    files.remove(this.dirOfDeletedFiles);
+    return files;
   }
 
   private int numberOfFiles(final File dir) {
-    return dir.listFiles().length;
+    return listFiles(dir).size();
   }
 
   private void createPreviousFiles(final int mainId, final int fileCount, final int lineCount)

http://git-wip-us.apache.org/repos/asf/geode/blob/d01db82c/geode-core/src/test/java/org/apache/geode/internal/util/ArrayUtilsJUnitTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/util/ArrayUtilsJUnitTest.java b/geode-core/src/test/java/org/apache/geode/internal/util/ArrayUtilsJUnitTest.java
deleted file mode 100644
index 3ec8b12..0000000
--- a/geode-core/src/test/java/org/apache/geode/internal/util/ArrayUtilsJUnitTest.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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.geode.internal.util;
-
-import static org.junit.Assert.*;
-
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import org.apache.geode.test.junit.categories.UnitTest;
-
-/**
- * Unit tests for {@link ArrayUtils}.
- *
- * @since GemFire 7.x
- */
-@Category(UnitTest.class)
-public class ArrayUtilsJUnitTest {
-
-  @Test
-  @SuppressWarnings("null")
-  public void testGetElementAtIndex() {
-    final Object[] array = {"test", "testing", "tested"};
-
-    assertEquals("test", ArrayUtils.getElementAtIndex(array, 0, null));
-    assertEquals("testing", ArrayUtils.getElementAtIndex(array, 1, null));
-    assertEquals("tested", ArrayUtils.getElementAtIndex(array, 2, null));
-  }
-
-  @Test
-  public void testGetElementAtIndexThrowingArrayIndexOutOfBoundsException() {
-    assertEquals("test", ArrayUtils.getElementAtIndex(new Object[0], 0, "test"));
-  }
-
-  @Test
-  public void testGetElementAtIndexThrowingArrayIndexOutOfBoundsExceptionOnNonEmptyArray() {
-    assertEquals("defaultValue",
-        ArrayUtils.getElementAtIndex(new Object[] {"test"}, 1, "defaultValue"));
-  }
-
-  @Test
-  public void testGetFirst() {
-    assertEquals("first", ArrayUtils.getFirst("first", "second", "third"));
-    assertEquals("null", ArrayUtils.getFirst("null", "nil", null));
-    assertEquals("test", ArrayUtils.getFirst("test"));
-    assertNull(ArrayUtils.getFirst((Object[]) null));
-    assertNull(ArrayUtils.getFirst(new Object[0]));
-    assertNull(ArrayUtils.getFirst(null, null, null));
-  }
-
-  @Test
-  public void testToString() {
-    final Object[] array = {"test", "testing", "tested"};
-
-    assertEquals("[test, testing, tested]", ArrayUtils.toString(array));
-  }
-
-  @Test
-  public void testToStringWithEmptyArray() {
-    assertEquals("[]", ArrayUtils.toString((new Object[0])));
-  }
-
-  @Test
-  public void testToStringWithNullArray() {
-    assertEquals("[]", ArrayUtils.toString((Object[]) null));
-  }
-
-  @Test
-  public void testGetIntegerArray() {
-    final Integer[] array = ArrayUtils.toIntegerArray(new int[] {0, 1, 2, 4, 8});
-
-    assertNotNull(array);
-    assertEquals(5, array.length);
-    assertEquals(0, array[0].intValue());
-    assertEquals(1, array[1].intValue());
-    assertEquals(2, array[2].intValue());
-    assertEquals(4, array[3].intValue());
-    assertEquals(8, array[4].intValue());
-  }
-
-  @Test
-  public void testGetIntegerArrayWithEmptyArray() {
-    final Integer[] array = ArrayUtils.toIntegerArray(new int[0]);
-
-    assertNotNull(array);
-    assertEquals(0, array.length);
-  }
-
-  @Test
-  @SuppressWarnings("null")
-  public void testGetIntegerArrayWithNullArray() {
-    final Integer[] array = ArrayUtils.toIntegerArray(null);
-
-    assertNotNull(array);
-    assertEquals(0, array.length);
-  }
-
-  @Test
-  public void testFromBytesToByteArray() {
-    int count = 0;
-    final byte[][] array = new byte[10][5];
-    for (int i = 0; i < array.length; i++) {
-      for (int j = 0; j < array[i].length; j++) {
-        array[i][j] = (byte) ++count;
-      }
-    }
-    assertEquals(50, count);
-
-    count = 0;
-    final Byte[][] byteArray = ArrayUtils.toByteArray(array);
-    for (int i = 0; i < byteArray.length; i++) {
-      for (int j = 0; j < byteArray[i].length; j++) {
-        assertEquals((byte) ++count, byteArray[i][j].byteValue());
-      }
-    }
-    assertEquals(50, count);
-  }
-
-  @Test
-  public void testFromByteArrayToBytes() {
-    int count = 100;
-    final Byte[][] byteArray = new Byte[5][10];
-    for (int i = 0; i < byteArray.length; i++) {
-      for (int j = 0; j < byteArray[i].length; j++) {
-        byteArray[i][j] = (byte) --count;
-      }
-    }
-    assertEquals(50, count);
-
-    count = 100;
-    final byte[][] array = ArrayUtils.toBytes(byteArray);
-    for (int i = 0; i < array.length; i++) {
-      for (int j = 0; j < array[i].length; j++) {
-        assertEquals((byte) --count, array[i][j]);
-      }
-    }
-    assertEquals(50, count);
-  }
-
-  @Test
-  public void testFromEmptyBytesToByteArray() {
-    final byte[][] array = new byte[0][0];
-    assertArrayEquals(new Byte[0][0], ArrayUtils.toByteArray(array));
-  }
-
-  @Test
-  public void testFromNullBytesToByteArray() {
-    final byte[][] array = null;
-    assertNull(ArrayUtils.toByteArray(array));
-  }
-
-  @Test
-  public void testFromEmptyByteArrayToBytes() {
-    final Byte[][] byteArray = new Byte[0][0];
-    assertArrayEquals(new byte[0][0], ArrayUtils.toBytes(byteArray));
-  }
-
-  @Test
-  public void testFromNullByteArrayToBytes() {
-    final Byte[][] byteArray = null;
-    assertNull(ArrayUtils.toBytes(byteArray));
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/geode/blob/d01db82c/geode-core/src/test/java/org/apache/geode/internal/util/ArrayUtilsTest.java
----------------------------------------------------------------------
diff --git a/geode-core/src/test/java/org/apache/geode/internal/util/ArrayUtilsTest.java b/geode-core/src/test/java/org/apache/geode/internal/util/ArrayUtilsTest.java
new file mode 100644
index 0000000..70da91b
--- /dev/null
+++ b/geode-core/src/test/java/org/apache/geode/internal/util/ArrayUtilsTest.java
@@ -0,0 +1,219 @@
+/*
+ * 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.geode.internal.util;
+
+import static org.apache.geode.internal.util.ArrayUtils.*;
+import static org.assertj.core.api.Assertions.*;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TestName;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.geode.test.junit.categories.UnitTest;
+
+/**
+ * Unit tests for {@link ArrayUtils}.
+ *
+ * @since GemFire 7.x
+ */
+@Category(UnitTest.class)
+@SuppressWarnings("null")
+public class ArrayUtilsTest {
+
+  @Rule
+  public TestName testName = new TestName();
+
+  @Test
+  public void testGetElementAtIndex() {
+    Object[] arrayOfThree = new Object[] {"test", "testing", "tested"};
+
+    assertThat(getElementAtIndex(arrayOfThree, 0, null)).isEqualTo("test");
+    assertThat(getElementAtIndex(arrayOfThree, 1, null)).isEqualTo("testing");
+    assertThat(getElementAtIndex(arrayOfThree, 2, null)).isEqualTo("tested");
+  }
+
+  @Test
+  public void getElementAtIndex_emptyArray_returnsDefaultValue() {
+    Object[] emptyArray = new Object[] {};
+    String defaultValue = this.testName.getMethodName();
+
+    assertThat(getElementAtIndex(emptyArray, 0, defaultValue)).isEqualTo(defaultValue);
+  }
+
+  @Test
+  public void getElementAtIndex_emptyArray_returnsNullDefaultValue() {
+    Object[] emptyArray = new Object[] {};
+
+    assertThat(getElementAtIndex(emptyArray, 0, null)).isNull();
+  }
+
+  @Test
+  public void getElementAtIndex_indexOutOfBounds_returnsDefaultValue() {
+    Object[] arrayOfOne = new Object[] {"test"};
+    String defaultValue = this.testName.getMethodName();
+
+    assertThat(getElementAtIndex(arrayOfOne, 2, defaultValue)).isEqualTo(defaultValue);
+  }
+
+  @Test
+  public void getElementAtIndex_empty_indexOutOfBounds_returnsDefaultValue() {
+    Object[] emptyArray = new Object[] {};
+    String defaultValue = this.testName.getMethodName();
+
+    assertThat(getElementAtIndex(emptyArray, 2, defaultValue)).isEqualTo(defaultValue);
+  }
+
+  @Test
+  public void getFirst_array_returnsFirstElement() {
+    assertThat(getFirst("first", "second", "third")).isEqualTo("first");
+  }
+
+  @Test
+  public void getFirst_arrayContainingNull_returnsFirstElement() {
+    assertThat(getFirst("null", "nil", null)).isEqualTo("null");
+  }
+
+  @Test
+  public void getFirst_oneElement_returnsFirstElement() {
+    assertThat(getFirst("test")).isEqualTo("test");
+  }
+
+  @Test
+  public void getFirst_null_returnsNull() {
+    assertThat(getFirst((Object[]) null)).isNull();
+  }
+
+  @Test
+  public void getFirst_empty_returnsNull() {
+    assertThat(getFirst(new Object[0])).isNull();
+  }
+
+  @Test
+  public void getFirst_arrayOfNullValues_returnsNull() {
+    assertThat((Object) getFirst(null, null, null)).isNull();
+  }
+
+  @Test
+  public void toString_returnsOrderedStringInBrackets() {
+    Object[] arrayOfThree = new Object[] {"test", "testing", "tested"};
+
+    assertThat(ArrayUtils.toString(arrayOfThree)).isEqualTo("[test, testing, tested]");
+  }
+
+  @Test
+  public void toString_empty_returnsEmptyBrackets() {
+    assertThat(ArrayUtils.toString((new Object[0]))).isEqualTo("[]");
+  }
+
+  @Test
+  public void toString_null_returnsEmptyBrackets() {
+    assertThat(ArrayUtils.toString((Object[]) null)).isEqualTo("[]");
+  }
+
+  @Test
+  public void toIntegerArray_returnsOrderedArray() {
+    int[] sequence = new int[] {0, 1, 2, 4, 8};
+
+    assertThat(toIntegerArray(sequence)).isNotNull().hasSize(sequence.length).containsExactly(0, 1,
+        2, 4, 8);
+  }
+
+  @Test
+  public void toIntegerArray_empty_returnsEmptyArray() {
+    assertThat(toIntegerArray(new int[] {})).isNotNull().hasSize(0);
+  }
+
+  @Test
+  public void toIntegerArray_null_returnsEmptyArray() {
+    assertThat(toIntegerArray(null)).isNotNull().hasSize(0);
+  }
+
+  @Test
+  public void toByteArray_returnsBytes() {
+    int count = 0;
+    byte[][] array = new byte[10][5];
+    for (int i = 0; i < array.length; i++) {
+      for (int j = 0; j < array[i].length; j++) {
+        array[i][j] = (byte) ++count;
+      }
+    }
+    assertThat(count).isEqualTo(50);
+
+    count = 0;
+    Byte[][] byteArray = toByteArray(array);
+    for (int i = 0; i < byteArray.length; i++) {
+      for (int j = 0; j < byteArray[i].length; j++) {
+        assertThat(byteArray[i][j].byteValue()).isEqualTo((byte) ++count);
+      }
+    }
+    assertThat(count).isEqualTo(50);
+  }
+
+  @Test
+  public void toBytes_returnsPrimitiveBytes() {
+    int count = 100;
+    Byte[][] byteArray = new Byte[5][10];
+    for (int i = 0; i < byteArray.length; i++) {
+      for (int j = 0; j < byteArray[i].length; j++) {
+        byteArray[i][j] = (byte) --count;
+      }
+    }
+    assertThat(count).isEqualTo(50);
+
+    count = 100;
+    byte[][] array = toBytes(byteArray);
+    for (int i = 0; i < array.length; i++) {
+      for (int j = 0; j < array[i].length; j++) {
+        assertThat(array[i][j]).isEqualTo((byte) --count);
+      }
+    }
+    assertThat(count).isEqualTo(50);
+  }
+
+  @Test
+  public void toByteArray_empty_returnsEmptyBytes() {
+    byte[][] array = new byte[0][0];
+    assertThat(toByteArray(array)).isEqualTo(new Byte[0][0]);
+  }
+
+  @Test
+  public void toByteArray_null_returnsNull() {
+    byte[][] array = null;
+    assertThat(toByteArray(array)).isNull();
+  }
+
+  @Test
+  public void toBytes_empty_returnsEmpty() {
+    Byte[][] byteArray = new Byte[0][0];
+    assertThat(toBytes(byteArray)).isEqualTo(new byte[0][0]);
+  }
+
+  @Test
+  public void toBytes_null_returnsNull() {
+    Byte[][] byteArray = null;
+    assertThat(toBytes(byteArray)).isNull();
+  }
+
+  @Test
+  public void asList_returnsModifiableList() throws Exception {
+    List<String> modifiable = asList("Larry", "Moe", "Curly");
+    assertThat(modifiable.remove("Curly")).isTrue();
+    assertThat(modifiable).contains("Larry", "Moe").doesNotContain("Curly");
+  }
+}