| /** |
| * 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.fs; |
| |
| import org.junit.Test; |
| import static org.junit.Assert.*; |
| |
| public class TestVolumeId { |
| |
| @Test |
| public void testEquality() { |
| final VolumeId id1 = new HdfsVolumeId(new byte[] { (byte)0, (byte)0 }); |
| testEq(true, id1, id1); |
| |
| final VolumeId id2 = new HdfsVolumeId(new byte[] { (byte)0, (byte)1 }); |
| testEq(true, id2, id2); |
| testEq(false, id1, id2); |
| |
| final VolumeId id3 = new HdfsVolumeId(new byte[] { (byte)1, (byte)0 }); |
| testEq(true, id3, id3); |
| testEq(false, id1, id3); |
| |
| // same as 2, but "invalid": |
| final VolumeId id2copy1 = new HdfsVolumeId(new byte[] { (byte)0, (byte)1 }); |
| |
| testEq(true, id2, id2copy1); |
| |
| // same as 2copy1: |
| final VolumeId id2copy2 = new HdfsVolumeId(new byte[] { (byte)0, (byte)1 }); |
| |
| testEq(true, id2, id2copy2); |
| |
| testEqMany(true, new VolumeId[] { id2, id2copy1, id2copy2 }); |
| |
| testEqMany(false, new VolumeId[] { id1, id2, id3 }); |
| } |
| |
| @SuppressWarnings("unchecked") |
| private <T> void testEq(final boolean eq, Comparable<T> id1, Comparable<T> id2) { |
| final int h1 = id1.hashCode(); |
| final int h2 = id2.hashCode(); |
| |
| // eq reflectivity: |
| assertTrue(id1.equals(id1)); |
| assertTrue(id2.equals(id2)); |
| assertEquals(0, id1.compareTo((T)id1)); |
| assertEquals(0, id2.compareTo((T)id2)); |
| |
| // eq symmetry: |
| assertEquals(eq, id1.equals(id2)); |
| assertEquals(eq, id2.equals(id1)); |
| |
| // null comparison: |
| assertFalse(id1.equals(null)); |
| assertFalse(id2.equals(null)); |
| |
| // compareTo: |
| assertEquals(eq, 0 == id1.compareTo((T)id2)); |
| assertEquals(eq, 0 == id2.compareTo((T)id1)); |
| // compareTo must be antisymmetric: |
| assertEquals(sign(id1.compareTo((T)id2)), -sign(id2.compareTo((T)id1))); |
| |
| // compare with null should never return 0 to be consistent with #equals(): |
| assertTrue(id1.compareTo(null) != 0); |
| assertTrue(id2.compareTo(null) != 0); |
| |
| // check that hash codes did not change: |
| assertEquals(h1, id1.hashCode()); |
| assertEquals(h2, id2.hashCode()); |
| if (eq) { |
| // in this case the hash codes must be the same: |
| assertEquals(h1, h2); |
| } |
| } |
| |
| private static int sign(int x) { |
| if (x == 0) { |
| return 0; |
| } else if (x > 0) { |
| return 1; |
| } else { |
| return -1; |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private <T> void testEqMany(final boolean eq, Comparable<T>... volumeIds) { |
| Comparable<T> vidNext; |
| int sum = 0; |
| for (int i=0; i<volumeIds.length; i++) { |
| if (i == volumeIds.length - 1) { |
| vidNext = volumeIds[0]; |
| } else { |
| vidNext = volumeIds[i + 1]; |
| } |
| testEq(eq, volumeIds[i], vidNext); |
| sum += sign(volumeIds[i].compareTo((T)vidNext)); |
| } |
| // the comparison relationship must always be acyclic: |
| assertTrue(sum < volumeIds.length); |
| } |
| |
| /* |
| * Test HdfsVolumeId(new byte[0]) instances: show that we permit such |
| * objects, they are still valid, and obey the same equality |
| * rules other objects do. |
| */ |
| @Test |
| public void testIdEmptyBytes() { |
| final VolumeId idEmpty1 = new HdfsVolumeId(new byte[0]); |
| assertTrue(idEmpty1.isValid()); |
| final VolumeId idEmpty2 = new HdfsVolumeId(new byte[0]); |
| assertTrue(idEmpty2.isValid()); |
| final VolumeId idNotEmpty = new HdfsVolumeId(new byte[] { (byte)1 }); |
| assertTrue(idNotEmpty.isValid()); |
| |
| testEq(true, idEmpty1, idEmpty2); |
| testEq(false, idEmpty1, idNotEmpty); |
| testEq(false, idEmpty2, idNotEmpty); |
| } |
| |
| /* |
| * Test the VolumeId.INVALID_VOLUME_ID singleton. |
| */ |
| @Test |
| public void testInvalidId() { |
| try { |
| new HdfsVolumeId(null); |
| assertTrue("NPE expected.", false); |
| } catch (NullPointerException npe) { |
| // okay |
| } |
| final VolumeId idEmpty = new HdfsVolumeId(new byte[] {}); |
| final VolumeId idNotEmpty = new HdfsVolumeId(new byte[] { (byte)1 }); |
| |
| testEq(false, VolumeId.INVALID_VOLUME_ID, idNotEmpty); |
| testEq(false, VolumeId.INVALID_VOLUME_ID, idEmpty); |
| |
| testEqMany(true, |
| new VolumeId[] { |
| VolumeId.INVALID_VOLUME_ID, |
| VolumeId.INVALID_VOLUME_ID, |
| VolumeId.INVALID_VOLUME_ID } ); |
| testEqMany(false, |
| new VolumeId[] { |
| VolumeId.INVALID_VOLUME_ID, |
| idEmpty, |
| idNotEmpty }); |
| } |
| |
| /* |
| * test #toString() for typical VolumeId equality classes |
| */ |
| @Test |
| public void testToString() { |
| // The #toString() return value is only checked for != null. |
| // We cannot assert more. |
| String strInvalid = VolumeId.INVALID_VOLUME_ID.toString(); |
| assertNotNull(strInvalid); |
| |
| String strEmpty = new HdfsVolumeId(new byte[] {}).toString(); |
| assertNotNull(strEmpty); |
| |
| String strNotEmpty = new HdfsVolumeId(new byte[] { (byte)1 }).toString(); |
| assertNotNull(strNotEmpty); |
| } |
| |
| } |