Repository: TheAlgorithms/Java
Pull request #5595 (2024-10-06 05:22:29)

Add tests for `A5KeyStreamGenerator.java`, improve documentation
<!--
Thank you for your contribution!
In order to reduce the number of notifications sent to the maintainers, please:
- create your PR as draft, cf. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests,
- make sure that all of the CI checks pass,
- mark your PR as ready for review, cf. https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request#marking-a-pull-request-as-ready-for-review
-->

<!-- For completed items, change [ ] to [x] -->

- [x] I have read [CONTRIBUTING.md](https://github.com/TheAlgorithms/Java/blob/master/CONTRIBUTING.md).
- [x] This pull request is all my own work -- I have not plagiarized it.
- [x] All filenames are in PascalCase.
- [x] All functions and variable names follow Java naming conventions.
- [x] All new algorithms have a URL in their comments that points to Wikipedia or other similar explanations.
- [x] All new code is formatted with `clang-format -i --style=file path/to/your/file.java`

codecov-commenter: ## [Codecov](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5595?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 54.84%. Comparing base [(`f34fe4d`)](https://app.codecov.io/gh/TheAlgorithms/Java/commit/f34fe4d8408ac35cef900cfae022ffadfc007ea3?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms) to head [(`e6e021f`)](https://app.codecov.io/gh/TheAlgorithms/Java/commit/e6e021f55f136a8a5519f4b33cd3db5c5c3b5da0?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).

<details><summary>Additional details and impacted files</summary>


```diff
@@             Coverage Diff              @@
##             master    #5595      +/-   ##
============================================
+ Coverage     54.56%   54.84%   +0.28%     
- Complexity     3413     3432      +19     
============================================
  Files           535      535              
  Lines         15383    15384       +1     
  Branches       2935     2935              
============================================
+ Hits           8393     8438      +45     
+ Misses         6637     6590      -47     
- Partials        353      356       +3     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/TheAlgorithms/Java/pull/5595?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=TheAlgorithms).


Patch:
diff --git a/DIRECTORY.md b/DIRECTORY.md
index 2b4dc078..6e952412 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -633,6 +633,7 @@
             * [SingleBitOperationsTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/bitmanipulation/SingleBitOperationsTest.java)
           * ciphers
             * a5
+              * [A5KeyStreamGeneratorTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java)
               * [LFSRTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/a5/LFSRTest.java)
             * [AutokeyTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/AutokeyTest.java)
             * [BlowfishTest](https://github.com/TheAlgorithms/Java/blob/master/src/test/java/com/thealgorithms/ciphers/BlowfishTest.java)
diff --git a/src/main/java/com/thealgorithms/ciphers/a5/A5KeyStreamGenerator.java b/src/main/java/com/thealgorithms/ciphers/a5/A5KeyStreamGenerator.java
index 0b17a685..ee837ef4 100644
--- a/src/main/java/com/thealgorithms/ciphers/a5/A5KeyStreamGenerator.java
+++ b/src/main/java/com/thealgorithms/ciphers/a5/A5KeyStreamGenerator.java
@@ -2,15 +2,39 @@ package com.thealgorithms.ciphers.a5;
 
 import java.util.BitSet;
 
-// TODO: raise exceptions for improper use
+/**
+ * The A5KeyStreamGenerator class is responsible for generating key streams
+ * for the A5/1 encryption algorithm using a combination of Linear Feedback Shift Registers (LFSRs).
+ *
+ * <p>
+ * This class extends the CompositeLFSR and initializes a set of LFSRs with
+ * a session key and a frame counter to produce a pseudo-random key stream.
+ * </p>
+ *
+ * <p>
+ * Note: Proper exception handling for invalid usage is to be implemented.
+ * </p>
+ */
 public class A5KeyStreamGenerator extends CompositeLFSR {
 
     private BitSet initialFrameCounter;
     private BitSet frameCounter;
     private BitSet sessionKey;
     private static final int INITIAL_CLOCKING_CYCLES = 100;
-    private static final int KEY_STREAM_LENGTH = 228; // 28.5 bytes so we need to pad bytes or something
+    private static final int KEY_STREAM_LENGTH = 228;
 
+    /**
+     * Initializes the A5KeyStreamGenerator with the specified session key and frame counter.
+     *
+     * <p>
+     * This method sets up the internal state of the LFSRs using the provided
+     * session key and frame counter. It creates three LFSRs with specific
+     * configurations and initializes them.
+     * </p>
+     *
+     * @param sessionKey a BitSet representing the session key used for key stream generation.
+     * @param frameCounter a BitSet representing the frame counter that influences the key stream.
+     */
     @Override
     public void initialize(BitSet sessionKey, BitSet frameCounter) {
         this.sessionKey = sessionKey;
@@ -26,10 +50,26 @@ public class A5KeyStreamGenerator extends CompositeLFSR {
         registers.forEach(lfsr -> lfsr.initialize(sessionKey, frameCounter));
     }
 
+    /**
+     * Re-initializes the key stream generator with the original session key
+     * and frame counter. This method restores the generator to its initial
+     * state.
+     */
     public void reInitialize() {
         this.initialize(sessionKey, initialFrameCounter);
     }
 
+    /**
+     * Generates the next key stream of bits.
+     *
+     * <p>
+     * This method performs an initial set of clocking cycles and then retrieves
+     * a key stream of the specified length. After generation, it re-initializes
+     * the internal registers.
+     * </p>
+     *
+     * @return a BitSet containing the generated key stream bits.
+     */
     public BitSet getNextKeyStream() {
         for (int cycle = 1; cycle <= INITIAL_CLOCKING_CYCLES; ++cycle) {
             this.clock();
@@ -45,12 +85,37 @@ public class A5KeyStreamGenerator extends CompositeLFSR {
         return result;
     }
 
+    /**
+     * Re-initializes the registers for the LFSRs.
+     *
+     * <p>
+     * This method increments the frame counter and re-initializes each LFSR
+     * with the current session key and frame counter.
+     * </p>
+     */
     private void reInitializeRegisters() {
         incrementFrameCounter();
         registers.forEach(lfsr -> lfsr.initialize(sessionKey, frameCounter));
     }
 
+    /**
+     * Increments the current frame counter.
+     *
+     * <p>
+     * This method uses a utility function to increment the frame counter,
+     * which influences the key stream generation process.
+     * </p>
+     */
     private void incrementFrameCounter() {
         Utils.increment(frameCounter, FRAME_COUNTER_LENGTH);
     }
+
+    /**
+     * Retrieves the current frame counter.
+     *
+     * @return a BitSet representing the current state of the frame counter.
+     */
+    public BitSet getFrameCounter() {
+        return frameCounter;
+    }
 }


Test patch:
diff --git a/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java b/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java
new file mode 100644
index 00000000..bb18d450
--- /dev/null
+++ b/src/test/java/com/thealgorithms/ciphers/a5/A5KeyStreamGeneratorTest.java
@@ -0,0 +1,60 @@
+package com.thealgorithms.ciphers.a5;
+
+import static com.thealgorithms.ciphers.a5.A5KeyStreamGenerator.FRAME_COUNTER_LENGTH;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+import java.util.BitSet;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class A5KeyStreamGeneratorTest {
+
+    private A5KeyStreamGenerator keyStreamGenerator;
+    private BitSet sessionKey;
+    private BitSet frameCounter;
+
+    @BeforeEach
+    void setUp() {
+        keyStreamGenerator = new A5KeyStreamGenerator();
+
+        // Initialize session key and frame counter for testing
+        sessionKey = BitSet.valueOf(new long[] {0b1010101010101010L}); // Example 16-bit key
+        frameCounter = BitSet.valueOf(new long[] {0b0000000000000001L}); // Example 16-bit frame counter
+        keyStreamGenerator.initialize(sessionKey, frameCounter);
+    }
+
+    @Test
+    void testInitialization() {
+        // Verify that the internal state is set up correctly
+        assertNotNull(keyStreamGenerator, "KeyStreamGenerator should be initialized");
+    }
+
+    @Test
+    void testIncrementFrameCounter() {
+        // Generate key stream to increment the frame counter
+        keyStreamGenerator.getNextKeyStream();
+
+        // The frame counter should have been incremented
+        BitSet incrementedFrameCounter = keyStreamGenerator.getFrameCounter();
+
+        // Check if the incremented frame counter is expected
+        BitSet expectedFrameCounter = (BitSet) frameCounter.clone();
+        Utils.increment(expectedFrameCounter, FRAME_COUNTER_LENGTH);
+
+        assertEquals(expectedFrameCounter, incrementedFrameCounter, "Frame counter should be incremented after generating key stream");
+    }
+
+    @Test
+    void testGetNextKeyStreamProducesDifferentOutputs() {
+        // Generate a key stream
+        BitSet firstKeyStream = keyStreamGenerator.getNextKeyStream();
+
+        // Generate another key stream
+        BitSet secondKeyStream = keyStreamGenerator.getNextKeyStream();
+
+        // Assert that consecutive key streams are different
+        assertNotEquals(firstKeyStream, secondKeyStream, "Consecutive key streams should be different");
+    }
+}