Files
Java/src/test/java/com/thealgorithms/bitmanipulation/BitRotateTest.java
Yajunesh MR 82ff14c36e feat: Add BitRotate utility for circular bit rotations (#7011)
* feat: Add BitRotate utility for circular bit rotations

* feat: Add BitRotate utility for circular bit rotations

* feat: Add BitRotate utility for circular bit rotations

* fix: Remove trailing spaces and add newline at EOF

---------

Co-authored-by: Yajunesh M R <yajunesh@Yajuneshs-MacBook-Pro.local>
2025-11-03 22:12:24 +01:00

206 lines
7.2 KiB
Java

package com.thealgorithms.bitmanipulation;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
/**
* Unit tests for BitRotate class covering typical, boundary, and edge cases.
* Tests verify correct behavior for 32-bit circular bit rotations.
*
* @author Yajunesh
*/
public class BitRotateTest {
// ===== rotateLeft Tests =====
@Test
public void testRotateLeftBasic() {
// Basic left rotation
assertEquals(0b00000000_00000000_00000000_00000010, BitRotate.rotateLeft(1, 1));
assertEquals(0b00000000_00000000_00000000_00000100, BitRotate.rotateLeft(1, 2));
assertEquals(0b00000000_00000000_00000000_00001000, BitRotate.rotateLeft(1, 3));
}
@Test
public void testRotateLeftWithCarry() {
// Test bits carrying from left to right
// Binary: 10000000_00000000_00000000_00000001
int value = 0x80000001;
// After left rotate by 1: 00000000_00000000_00000000_00000011
assertEquals(3, BitRotate.rotateLeft(value, 1));
// Binary: 11000000_00000000_00000000_00000000
value = 0xC0000000;
// After left rotate by 1: 10000000_00000000_00000000_00000001
assertEquals(0x80000001, BitRotate.rotateLeft(value, 1));
}
@Test
public void testRotateLeftShift32() {
// Shift of 32 should be same as shift of 0 (modulo behavior)
int value = 0x12345678;
assertEquals(value, BitRotate.rotateLeft(value, 32));
assertEquals(value, BitRotate.rotateLeft(value, 64));
assertEquals(value, BitRotate.rotateLeft(value, 96));
}
@Test
public void testRotateLeftShiftNormalization() {
// Test that shifts > 32 are properly normalized
int value = 1;
assertEquals(BitRotate.rotateLeft(value, 1), BitRotate.rotateLeft(value, 33));
assertEquals(BitRotate.rotateLeft(value, 5), BitRotate.rotateLeft(value, 37));
}
@Test
public void testRotateLeftZeroShift() {
// Zero shift should return original value
int value = 0xABCD1234;
assertEquals(value, BitRotate.rotateLeft(value, 0));
}
// ===== rotateRight Tests =====
@Test
public void testRotateRightBasic() {
// Basic right rotation
assertEquals(0b10000000_00000000_00000000_00000000, BitRotate.rotateRight(1, 1));
assertEquals(0b01000000_00000000_00000000_00000000, BitRotate.rotateRight(1, 2));
assertEquals(0b00100000_00000000_00000000_00000000, BitRotate.rotateRight(1, 3));
}
@Test
public void testRotateRightWithCarry() {
// Test bits carrying from right to left
// Binary: 00000000_00000000_00000000_00000011
int value = 3;
// After right rotate by 1: 10000000_00000000_00000000_00000001
assertEquals(0x80000001, BitRotate.rotateRight(value, 1));
// Binary: 00000000_00000000_00000000_00000001
value = 1;
// After right rotate by 1: 10000000_00000000_00000000_00000000
assertEquals(0x80000000, BitRotate.rotateRight(value, 1));
}
@Test
public void testRotateRightShift32() {
// Shift of 32 should be same as shift of 0 (modulo behavior)
int value = 0x9ABCDEF0;
assertEquals(value, BitRotate.rotateRight(value, 32));
assertEquals(value, BitRotate.rotateRight(value, 64));
assertEquals(value, BitRotate.rotateRight(value, 96));
}
@Test
public void testRotateRightShiftNormalization() {
// Test that shifts > 32 are properly normalized
int value = 1;
assertEquals(BitRotate.rotateRight(value, 1), BitRotate.rotateRight(value, 33));
assertEquals(BitRotate.rotateRight(value, 7), BitRotate.rotateRight(value, 39));
}
@Test
public void testRotateRightZeroShift() {
// Zero shift should return original value
int value = 0xDEADBEEF;
assertEquals(value, BitRotate.rotateRight(value, 0));
}
// ===== Edge Case Tests =====
@Test
public void testRotateLeftMaxValue() {
// Test with maximum integer value
int value = Integer.MAX_VALUE; // 0x7FFFFFFF
int rotated = BitRotate.rotateLeft(value, 1);
// MAX_VALUE << 1 should become 0xFFFFFFFE, but with rotation it becomes different
assertEquals(0xFFFFFFFE, rotated);
}
@Test
public void testRotateRightMinValue() {
// Test with minimum integer value (treated as unsigned)
int value = Integer.MIN_VALUE; // 0x80000000
int rotated = BitRotate.rotateRight(value, 1);
// MIN_VALUE >>> 1 should become 0x40000000, but with rotation from left
assertEquals(0x40000000, rotated);
}
@Test
public void testRotateAllOnes() {
// Test with all bits set
int value = 0xFFFFFFFF; // All ones
assertEquals(value, BitRotate.rotateLeft(value, 13));
assertEquals(value, BitRotate.rotateRight(value, 27));
}
@Test
public void testRotateAllZeros() {
// Test with all bits zero
int value = 0x00000000;
assertEquals(value, BitRotate.rotateLeft(value, 15));
assertEquals(value, BitRotate.rotateRight(value, 19));
}
// ===== Exception Tests =====
@Test
public void testRotateLeftNegativeShift() {
// Negative shifts should throw IllegalArgumentException
Exception exception = assertThrows(IllegalArgumentException.class, () -> BitRotate.rotateLeft(42, -1));
assertTrue(exception.getMessage().contains("negative"));
}
@Test
public void testRotateRightNegativeShift() {
// Negative shifts should throw IllegalArgumentException
Exception exception = assertThrows(IllegalArgumentException.class, () -> BitRotate.rotateRight(42, -5));
assertTrue(exception.getMessage().contains("negative"));
}
// ===== Complementary Operations Test =====
@Test
public void testRotateLeftRightComposition() {
// Rotating left then right by same amount should return original value
int original = 0x12345678;
int shift = 7;
int leftRotated = BitRotate.rotateLeft(original, shift);
int restored = BitRotate.rotateRight(leftRotated, shift);
assertEquals(original, restored);
}
@Test
public void testRotateRightLeftComposition() {
// Rotating right then left by same amount should return original value
int original = 0x9ABCDEF0;
int shift = 13;
int rightRotated = BitRotate.rotateRight(original, shift);
int restored = BitRotate.rotateLeft(rightRotated, shift);
assertEquals(original, restored);
}
@Test
public void testRotateLeft31IsSameAsRotateRight1() {
// Rotating left by 31 should be same as rotating right by 1
int value = 0x55555555;
assertEquals(BitRotate.rotateLeft(value, 31), BitRotate.rotateRight(value, 1));
}
@Test
public void testTraversals() {
// Test that methods don't throw exceptions
assertDoesNotThrow(() -> BitRotate.rotateLeft(1, 1));
assertDoesNotThrow(() -> BitRotate.rotateRight(1, 1));
}
}