@@ -114,4 +114,180 @@ public void testValidateAddsPortHttp() {
114114 Assert .assertTrue ("Validator did not add port 80 to http url" , isValid );
115115 }
116116
117+
118+ @ Test
119+ public void testValidateWithEmptyParams () {
120+ // Test with no form parameters - empty map
121+ Map <String , String > emptyParams = new HashMap <>();
122+ String expectedSignature = "zYQTYrRWXE7LtzbG4PfP7/bkkGo=" ; // hash of URL only
123+ boolean isValid = validator .validate (url , emptyParams , expectedSignature );
124+
125+ Assert .assertTrue ("Validation should succeed with empty parameters" , isValid );
126+ }
127+
128+ @ Test
129+ public void testValidateWithNullParams () {
130+ // Test with null parameters
131+ String expectedSignature = "zYQTYrRWXE7LtzbG4PfP7/bkkGo=" ; // hash of URL only
132+ boolean isValid = validator .validate (url , (Map <String , String >) null , expectedSignature );
133+
134+ Assert .assertTrue ("Validation should succeed with null parameters" , isValid );
135+ }
136+
137+ @ Test
138+ public void testValidateWithNoQueryParams () {
139+ // Test with URL that has no query parameters
140+ String urlNoQuery = "https://mycompany.com/myapp.php" ;
141+ String expectedSignature = "1xaxFBvyzXYvWplzNOSs28HWO94=" ;
142+ boolean isValid = validator .validate (urlNoQuery , params , expectedSignature );
143+
144+ Assert .assertTrue ("Validation should succeed with URL without query parameters" , isValid );
145+ }
146+
147+ @ Test
148+ public void testValidateIgnoresNonTwilioQueryParams () {
149+ // Test that non-Twilio query parameters in the URL are included in signature generation
150+ // (they are NOT ignored - they're part of the URL that gets signed)
151+ String urlWithExtraParams = "https://mycompany.com/myapp.php?foo=1&bar=2&type=thiswontbeusedinthesignaturegeneratorandsoshouldbeignored" ;
152+ String expectedSignature = "hYkNsTBttoNGkyCS0p+wWmQoRTg=" ;
153+ boolean isValid = validator .validate (urlWithExtraParams , params , expectedSignature );
154+
155+ Assert .assertTrue ("Validation should succeed - query params are part of URL signature" , isValid );
156+ }
157+
158+ @ Test
159+ public void testValidateWithUrlEncodedQueryParams () {
160+ // Test with URL encoded query parameters
161+ String urlEncoded = "https://mycompany.com/myapp.php?foo=hello%20world&bar=test%2Bvalue" ;
162+ String expectedSignature = "er2tvAP1Wx+iuTTE2BPgvEaN1cs=" ;
163+ boolean isValid = validator .validate (urlEncoded , params , expectedSignature );
164+
165+ Assert .assertTrue ("Validation should succeed with URL encoded query parameters" , isValid );
166+ }
167+
168+ @ Test
169+ public void testValidateWithSpecialCharactersInParams () {
170+ // Test with special characters in parameter values
171+ Map <String , String > specialParams = new HashMap <>();
172+ specialParams .put ("Message" , "Hello & goodbye! @#$%^*()" );
173+ specialParams .put ("From" , "+1 (415) 867-5309" );
174+ specialParams .put ("Special" , "unicode: ñáéíóú" );
175+
176+ String expectedSignature = "dCPiR4WtQ6QFN6pJh81CtlCcWLQ=" ;
177+ boolean isValid = validator .validate (url , specialParams , expectedSignature );
178+
179+ Assert .assertTrue ("Validation should succeed with special characters in parameters" , isValid );
180+ }
181+
182+ @ Test
183+ public void testValidateWithEmptyParameterValues () {
184+ // Test with empty string parameter values
185+ Map <String , String > emptyValueParams = new HashMap <>();
186+ emptyValueParams .put ("Digits" , "" );
187+ emptyValueParams .put ("CallSid" , "CA1234567890ABCDE" );
188+ emptyValueParams .put ("EmptyParam" , "" );
189+
190+ String expectedSignature = "9HHp/OqQMEwdrVebHDdA/+tqjX8=" ;
191+ boolean isValid = validator .validate (url , emptyValueParams , expectedSignature );
192+
193+ Assert .assertTrue ("Validation should succeed with empty parameter values" , isValid );
194+ }
195+
196+ @ Test
197+ public void testValidateWithNullParameterValues () {
198+ // Test with null parameter values (treated as empty strings)
199+ Map <String , String > nullValueParams = new HashMap <>();
200+ nullValueParams .put ("Digits" , null );
201+ nullValueParams .put ("CallSid" , "CA1234567890ABCDE" );
202+ nullValueParams .put ("NullParam" , null );
203+
204+ String expectedSignature = "L9lTTwIlxM1xGAtLRwhOSZggRhM=" ;
205+ boolean isValid = validator .validate (url , nullValueParams , expectedSignature );
206+
207+ Assert .assertTrue ("Validation should succeed with null parameter values" , isValid );
208+ }
209+
210+ @ Test
211+ public void testValidateParameterKeySorting () {
212+ // Test that parameter keys are properly sorted alphabetically
213+ Map <String , String > unsortedParams = new HashMap <>();
214+ unsortedParams .put ("Zebra" , "last" );
215+ unsortedParams .put ("Alpha" , "first" );
216+ unsortedParams .put ("Beta" , "second" );
217+ unsortedParams .put ("Gamma" , "third" );
218+
219+ String expectedSignature = "enveUe73ZTVLAekHxez3Qx6JuuQ=" ;
220+ boolean isValid = validator .validate (url , unsortedParams , expectedSignature );
221+
222+ Assert .assertTrue ("Validation should succeed with alphabetically sorted parameters" , isValid );
223+ }
224+
225+ @ Test
226+ public void testValidateWithInternationalCharactersInUrl () {
227+ // Test with international characters in URL
228+ String intlUrl = "https://mycompany.com/webhook/España?año=2023" ;
229+ String expectedSignature = "G/Hx6mqqnjUNlPAoi2Sp9bGst0g=" ;
230+ boolean isValid = validator .validate (intlUrl , params , expectedSignature );
231+
232+ Assert .assertTrue ("Validation should succeed with international characters in URL" , isValid );
233+ }
234+
235+ @ Test
236+ public void testValidateWithCaseSensitiveParameterKeys () {
237+ // Test that parameter keys are case sensitive
238+ Map <String , String > caseParams = new HashMap <>();
239+ caseParams .put ("callSid" , "lowercase" );
240+ caseParams .put ("CallSid" , "uppercase" ); // Different from callSid
241+ caseParams .put ("CALLSID" , "allcaps" );
242+
243+ String expectedSignature = "jDK7WKT8wiNrwggd4ceTv4e1MJ4=" ;
244+ boolean isValid = validator .validate (url , caseParams , expectedSignature );
245+
246+ Assert .assertTrue ("Validation should succeed with case-sensitive parameter keys" , isValid );
247+ }
248+
249+ @ Test
250+ public void testValidateWithMalformedUrlStillWorks () {
251+ // Test that validation handles URLs gracefully even with unusual formatting
252+ String malformedUrl = "https://mycompany.com:443//myapp.php?foo=1&bar=2" ;
253+ String expectedSignature = "A9lH3u16NjyiiM/+wylw5rirFUs=" ; // Signature for the malformed URL as-is
254+ boolean isValid = validator .validate (malformedUrl , params , expectedSignature );
255+
256+ Assert .assertTrue ("Validation should handle malformed URLs gracefully" , isValid );
257+ }
258+
259+ @ Test
260+ public void testValidateWithDifferentProtocols () {
261+ // Test validation with different protocols
262+ String httpUrl = url .replace ("https" , "http" );
263+ String expectedSignature = "0ZXoZLH/DfblKGATFgpif+LLRf4=" ;
264+ boolean isValid = validator .validate (httpUrl , params , expectedSignature );
265+
266+ Assert .assertTrue ("Validation should work with HTTP protocol" , isValid );
267+ }
268+
269+ @ Test
270+ public void testValidateFailsWithWrongSignature () {
271+ // Test that validation properly fails with incorrect signature
272+ String wrongSignature = "IncorrectSignatureValue123=" ;
273+ boolean isValid = validator .validate (url , params , wrongSignature );
274+
275+ Assert .assertFalse ("Validation should fail with incorrect signature" , isValid );
276+ }
277+
278+ @ Test
279+ public void testValidateFailsWithNullSignature () {
280+ // Test that validation properly fails with null signature
281+ boolean isValid = validator .validate (url , params , null );
282+
283+ Assert .assertFalse ("Validation should fail with null signature" , isValid );
284+ }
285+
286+ @ Test
287+ public void testValidateFailsWithEmptySignature () {
288+ // Test that validation properly fails with empty signature
289+ boolean isValid = validator .validate (url , params , "" );
290+ Assert .assertFalse ("Validation should fail with empty signature" , isValid );
291+ }
292+
117293}
0 commit comments