From 91866cbc953b7fdd9ff9fd6060bf98b3d45b4353 Mon Sep 17 00:00:00 2001 From: aSemy Date: Mon, 8 Jan 2024 20:16:20 +0100 Subject: [PATCH] make IBAN random generation independent per generation - create new instances of Randoms where necessary, so that adding/removing IBAN entries won't affect any IBANs that are subsequently generated. - update tests to use assertAll, so it's easier to check & update each value --- src/main/java/org/iban4j/Iban.java | 10 +++++-- .../org/iban4j/bban/BbanStructureEntry.java | 6 ++++ src/test/java/org/iban4j/IbanTest.java | 18 +++++++----- .../iban4j/bban/BbanStructureEntryTest.java | 29 ++++++++++++------- 4 files changed, 42 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/iban4j/Iban.java b/src/main/java/org/iban4j/Iban.java index f7b1980..2998b21 100644 --- a/src/main/java/org/iban4j/Iban.java +++ b/src/main/java/org/iban4j/Iban.java @@ -413,11 +413,17 @@ public Iban build(boolean validate) throws IbanFormatException, */ public Iban buildRandom() throws IbanFormatException, IllegalArgumentException, UnsupportedCountryException { + + // Create a new seeded Random, so it doesn't matter how this Random is used, it won't affect subsequent usages + // of the original Random. (which can impact seeded behaviour when many IBANs are generated or the number of + // IBAN entries change). + final Random random = new Random(this.random.nextInt()); + if (countryCode == null) { List countryCodes = BbanStructure.supportedCountries(); this.countryCode(countryCodes.get(random.nextInt(countryCodes.size()))); } - fillMissingFieldsRandomly(); + fillMissingFieldsRandomly(random); return build(); } @@ -511,7 +517,7 @@ private void require(final CountryCode countryCode, } } - private void fillMissingFieldsRandomly() { + private void fillMissingFieldsRandomly(final Random random) { final BbanStructure structure = BbanStructure.forCountry(countryCode); if (structure == null) { diff --git a/src/main/java/org/iban4j/bban/BbanStructureEntry.java b/src/main/java/org/iban4j/bban/BbanStructureEntry.java index d0c5152..f06cd50 100644 --- a/src/main/java/org/iban4j/bban/BbanStructureEntry.java +++ b/src/main/java/org/iban4j/bban/BbanStructureEntry.java @@ -122,6 +122,12 @@ public String getRandom() { } public String getRandom(Random random) { + + // Create a new seeded Random, so it doesn't matter how this Random is used, it won't affect subsequent usages + // of the original Random. (which can impact seeded behaviour when many IBANs are generated or the number of + // IBAN entries change). + random = new Random(random.nextInt()); + StringBuilder s = new StringBuilder(); char[] charChoices = charByCharacterType.get(characterType); if (charChoices == null) { diff --git a/src/test/java/org/iban4j/IbanTest.java b/src/test/java/org/iban4j/IbanTest.java index 5626083..c71d555 100644 --- a/src/test/java/org/iban4j/IbanTest.java +++ b/src/test/java/org/iban4j/IbanTest.java @@ -287,11 +287,12 @@ public void ibanConstructionRandom() { } @Test - @Disabled public void ibanConstructionSeeded() { - assertIbanUtilRandomWithSeedEquals("FR87 8734 4468 89P1 RIYK UO5K 809", 1); - assertIbanUtilRandomWithSeedEquals("FI79 2079 0697 8464 44", 2); - assertIbanUtilRandomWithSeedEquals("FO71 0018 2949 1527 41", 3); + assertAll( + () -> assertIbanUtilRandomWithSeedEquals("GL41 1918 0836 9682 13", 1), + () -> assertIbanUtilRandomWithSeedEquals("FR17 0679 7098 8804 5NYW S75F D50", 2), + () -> assertIbanUtilRandomWithSeedEquals("EG45 0882 2804 0304 6660 9507 6091 3", 3) + ); } private static void assertIbanUtilRandomWithSeedEquals( @@ -307,11 +308,12 @@ private static void assertIbanUtilRandomWithSeedEquals( } @Test - @Disabled public void ibanBuilderConstructionSeeded() { - assertIbanBuilderRandomWithSeedEquals("FR87 8734 4468 89P1 RIYK UO5K 809", 1); - assertIbanBuilderRandomWithSeedEquals("FI79 2079 0697 8464 44", 2); - assertIbanBuilderRandomWithSeedEquals("FO71 0018 2949 1527 41", 3); + assertAll( + () -> assertIbanBuilderRandomWithSeedEquals("GL41 1918 0836 9682 13", 1), + () -> assertIbanBuilderRandomWithSeedEquals("FR17 0679 7098 8804 5NYW S75F D50", 2), + () -> assertIbanBuilderRandomWithSeedEquals("EG45 0882 2804 0304 6660 9507 6091 3", 3) + ); } private static void assertIbanBuilderRandomWithSeedEquals( diff --git a/src/test/java/org/iban4j/bban/BbanStructureEntryTest.java b/src/test/java/org/iban4j/bban/BbanStructureEntryTest.java index 14f95f5..a780341 100644 --- a/src/test/java/org/iban4j/bban/BbanStructureEntryTest.java +++ b/src/test/java/org/iban4j/bban/BbanStructureEntryTest.java @@ -1,11 +1,12 @@ package org.iban4j.bban; +import org.junit.jupiter.api.Test; + import java.nio.CharBuffer; import java.util.Objects; import java.util.Random; import java.util.stream.Collectors; import java.util.stream.Stream; -import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -15,27 +16,33 @@ public class BbanStructureEntryTest { public void expectRandomAccountNumberIsDeterministicWhenSeeded() { BbanStructureEntry entry = BbanStructureEntry.accountNumber(10, 'a'); - assertSeededRandomBbanStructureEntryEquals(entry, "RAHJMYUWWK", 1); - assertSeededRandomBbanStructureEntryEquals(entry, "SGAVREIZNE", 2); - assertSeededRandomBbanStructureEntryEquals(entry, "SMMHQUVGJX", 3); + assertAll( + () -> assertSeededRandomBbanStructureEntryEquals(entry, "GYNPNTQMPP", 1), + () -> assertSeededRandomBbanStructureEntryEquals(entry, "ZBFUFVOHNJ", 2), + () -> assertSeededRandomBbanStructureEntryEquals(entry, "FHTOSEFCAR", 3) + ); } @Test public void expectRandomOwnerAccountNumberIsDeterministicWhenSeeded() { BbanStructureEntry entry = BbanStructureEntry.ownerAccountNumber(11, 'n'); - assertSeededRandomBbanStructureEntryEquals(entry, "58734446889", 1); - assertSeededRandomBbanStructureEntryEquals(entry, "82079069784", 2); - assertSeededRandomBbanStructureEntryEquals(entry, "40018294915", 3); + assertAll( + () -> assertSeededRandomBbanStructureEntryEquals(entry, "88511786533", 1), + () -> assertSeededRandomBbanStructureEntryEquals(entry, "33705581952", 2), + () -> assertSeededRandomBbanStructureEntryEquals(entry, "13164650831", 3) + ); } @Test public void expectRandomBankCodeIsDeterministicWhenSeeded() { BbanStructureEntry entry = BbanStructureEntry.bankCode(12, 'c'); - assertSeededRandomBbanStructureEntryEquals(entry, "XSJXQ4EAASPP", 1); - assertSeededRandomBbanStructureEntryEquals(entry, "4OKJX66R7O22", 2); - assertSeededRandomBbanStructureEntryEquals(entry, "EK6POILGJDLA", 3); + assertAll( + () -> assertSeededRandomBbanStructureEntryEquals(entry, "88FV9Z62HZ1T", 1), + () -> assertSeededRandomBbanStructureEntryEquals(entry, "T7F8TRELZ3I9", 2), + () -> assertSeededRandomBbanStructureEntryEquals(entry, "TXTOAA7SCPXB", 3) + ); } private static void assertSeededRandomBbanStructureEntryEquals( @@ -119,7 +126,7 @@ public void expectAlphabeticEntryGeneratesAllUppercaseLetters() { String distinctChars = getDistinctSortedChars(generated); assertEquals( - "ABCDEFGHIJKLMNOPQRSTUVWXYZ", + "ABCDEFGHIJKLMNOPQRSTUVWXYZ", distinctChars ); }