1
+ package com .thealgorithms .maths ;
2
+
3
+ import org .junit .jupiter .api .BeforeEach ;
4
+ import org .junit .jupiter .api .Test ;
5
+ import org .junit .jupiter .params .ParameterizedTest ;
6
+ import org .junit .jupiter .params .provider .MethodSource ;
7
+
8
+ import static org .junit .jupiter .api .Assertions .*;
9
+
10
+ /**
11
+ * Unit tests for the {@link SolovayStrassenPrimalityTest} class.
12
+ * This class tests the functionality of the Solovay-Strassen primality test implementation.
13
+ */
14
+ class SolovayStrassenPrimalityTestTest {
15
+
16
+ private static final int RANDOM_SEED = 123 ; // Seed for reproducibility
17
+ private SolovayStrassenPrimalityTest testInstance ;
18
+
19
+ /**
20
+ * Sets up a new instance of {@link SolovayStrassenPrimalityTest}
21
+ * before each test case, using a fixed random seed for consistency.
22
+ */
23
+ @ BeforeEach
24
+ void setUp () {
25
+ testInstance = SolovayStrassenPrimalityTest .getSolovayStrassenPrimalityTest (RANDOM_SEED );
26
+ }
27
+
28
+ /**
29
+ * Provides test cases for prime numbers with various values of n and k (iterations).
30
+ *
31
+ * @return an array of objects containing pairs of n and k values
32
+ */
33
+ static Object [][] primeNumbers () {
34
+ return new Object [][]{
35
+ {2 , 1 }, {3 , 1 }, {5 , 5 }, {7 , 10 },
36
+ {11 , 20 }, {13 , 10 }, {17 , 5 }, {19 , 1 }
37
+ };
38
+ }
39
+
40
+ /**
41
+ * Tests known prime numbers with various values of n and k (iterations).
42
+ *
43
+ * @param n the number to be tested for primality
44
+ * @param k the number of iterations to use in the primality test
45
+ */
46
+ @ ParameterizedTest
47
+ @ MethodSource ("primeNumbers" )
48
+ void testPrimeNumbersWithDifferentNAndK (int n , int k ) {
49
+ assertTrue (testInstance .solovayStrassen (n , k ), n + " should be prime" );
50
+ }
51
+
52
+ /**
53
+ * Provides test cases for composite numbers with various values of n and k (iterations).
54
+ *
55
+ * @return an array of objects containing pairs of n and k values
56
+ */
57
+ static Object [][] compositeNumbers () {
58
+ return new Object [][]{
59
+ {4 , 1 }, {6 , 5 }, {8 , 10 }, {9 , 20 },
60
+ {10 , 1 }, {12 , 5 }, {15 , 10 }
61
+ };
62
+ }
63
+
64
+ /**
65
+ * Tests known composite numbers with various values of n and k (iterations).
66
+ *
67
+ * @param n the number to be tested for primality
68
+ * @param k the number of iterations to use in the primality test
69
+ */
70
+ @ ParameterizedTest
71
+ @ MethodSource ("compositeNumbers" )
72
+ void testCompositeNumbersWithDifferentNAndK (int n , int k ) {
73
+ assertFalse (testInstance .solovayStrassen (n , k ), n + " should be composite" );
74
+ }
75
+
76
+ /**
77
+ * Tests edge cases for the primality test.
78
+ * This includes negative numbers and small integers (0 and 1).
79
+ */
80
+ @ Test
81
+ void testEdgeCases () {
82
+ assertFalse (testInstance .solovayStrassen (-1 , 10 ), "-1 should not be prime" );
83
+ assertFalse (testInstance .solovayStrassen (0 , 10 ), "0 should not be prime" );
84
+ assertFalse (testInstance .solovayStrassen (1 , 10 ), "1 should not be prime" );
85
+
86
+ // Test small primes and composites
87
+ assertTrue (testInstance .solovayStrassen (2 , 1 ), "2 is a prime number (single iteration)" );
88
+ assertFalse (testInstance .solovayStrassen (9 , 1 ), "9 is a composite number (single iteration)" );
89
+
90
+ // Test larger primes and composites
91
+ long largePrime = 104729 ; // Known large prime number
92
+ long largeComposite = 104730 ; // Known composite number (even)
93
+
94
+ assertTrue (testInstance .solovayStrassen (largePrime , 20 ), "104729 is a prime number" );
95
+ assertFalse (testInstance .solovayStrassen (largeComposite , 20 ), "104730 is a composite number" );
96
+
97
+ // Test very large numbers (may take longer)
98
+ long veryLargePrime = 512927357 ; // Near the upper limit of long
99
+ long veryLargeComposite = 512927358 ; // Composite (even)
100
+
101
+ assertTrue (testInstance .solovayStrassen (veryLargePrime , 20 ),
102
+ Long .MAX_VALUE - 1 + " is likely a prime number." );
103
+
104
+ assertFalse (testInstance .solovayStrassen (veryLargeComposite , 20 ),
105
+ Long .MAX_VALUE + " is a composite number." );
106
+ }
107
+
108
+ /**
109
+ * Tests the Jacobi symbol calculation directly for known values.
110
+ * This verifies that the Jacobi symbol method behaves as expected.
111
+ */
112
+ @ Test
113
+ void testJacobiSymbolCalculation () {
114
+ // Jacobi symbol (a/n) where n is odd and positive
115
+ int jacobi1 = testInstance .calculateJacobi (6 , 11 ); // Should return -1
116
+ int jacobi2 = testInstance .calculateJacobi (5 , 11 ); // Should return +1
117
+ int jacobi3 = testInstance .calculateJacobi (4 , 11 ); // Should return +1
118
+
119
+ assertEquals (-1 , jacobi1 );
120
+ assertEquals (+1 , jacobi2 );
121
+ assertEquals (+1 , jacobi3 );
122
+
123
+ // Edge case: Jacobi symbol with even n or non-positive n
124
+ int jacobi4 = testInstance .calculateJacobi (5 , -11 ); // Should return 0 (invalid)
125
+ int jacobi5 = testInstance .calculateJacobi (5 , 0 ); // Should return 0 (invalid)
126
+
127
+ assertEquals (0 , jacobi4 );
128
+ assertEquals (0 , jacobi5 );
129
+ }
130
+ }
0 commit comments