1616# Copyright (c) OWASP Foundation. All Rights Reserved.
1717
1818
19+ import unittest
1920from itertools import product
20- from unittest import TestCase
2121
2222from ddt import data , ddt , named_data , unpack
2323
2424from cyclonedx .schema import OutputFormat , SchemaVersion
25- from cyclonedx .validation import make_schemabased_validator
25+ from cyclonedx .validation import make_schemabased_validator , squeeze
2626
2727UNDEFINED_FORMAT_VERSION = {
2828 (OutputFormat .JSON , SchemaVersion .V1_1 ),
3131
3232
3333@ddt
34- class TestGetSchemabasedValidator (TestCase ):
34+ class TestGetSchemabasedValidator (unittest . TestCase ):
3535
3636 @named_data (* ([f'{ f .name } { v .name } ' , f , v ]
3737 for f , v
@@ -51,3 +51,121 @@ def test_as_expected(self, of: OutputFormat, sv: SchemaVersion) -> None:
5151 def test_fails_on_wrong_args (self , of : OutputFormat , sv : SchemaVersion , raises_regex : tuple ) -> None :
5252 with self .assertRaisesRegex (* raises_regex ):
5353 make_schemabased_validator (of , sv )
54+
55+
56+ class TestSqueeze (unittest .TestCase ):
57+
58+ def test_squeeze_size_minus_one_returns_original_text (self ) -> None :
59+ """Test that size=-1 returns original text unchanged."""
60+ self .assertEqual (squeeze ('hello world' , - 1 ), 'hello world' )
61+ self .assertEqual (squeeze ('' , - 1 ), '' )
62+ self .assertEqual (squeeze ('a' , - 1 ), 'a' )
63+ self .assertEqual (squeeze ('very long text that would normally be squeezed' , - 1 ),
64+ 'very long text that would normally be squeezed' )
65+
66+ def test_squeeze_size_zero_returns_empty_text (self ) -> None :
67+ """Test that size=-1 returns original text unchanged."""
68+ self .assertEqual (squeeze ('hello world' , 0 , '' ), '' )
69+ self .assertEqual (squeeze ('' , 0 , '' ), '' )
70+
71+ def test_squeeze_text_shorter_than_or_equal_size_returns_original (self ) -> None :
72+ """Test that text shorter than or equal to size returns original text."""
73+ self .assertEqual (squeeze ('hello' , 10 ), 'hello' )
74+ self .assertEqual (squeeze ('hello' , 5 ), 'hello' )
75+ self .assertEqual (squeeze ('' , 5 ), '' )
76+ self .assertEqual (squeeze ('a' , 5 ), 'a' )
77+ self .assertEqual (squeeze ('ab' , 10 ), 'ab' )
78+
79+ def test_squeeze_with_default_replacement (self ) -> None :
80+ """Test squeezing with default ' ... ' replacement."""
81+ self .assertEqual (squeeze ('hello world' , 8 ), 'h ... ld' )
82+ self .assertEqual (squeeze ('hello world' , 7 ), 'h ... d' )
83+ self .assertEqual (squeeze ('hello world' , 9 ), 'he ... ld' )
84+ self .assertEqual (squeeze ('hello world' , 10 ), 'he ... rld' )
85+ self .assertEqual (squeeze ('hello world' , 11 ), 'hello world' )
86+
87+ def test_squeeze_with_custom_replacement (self ) -> None :
88+ """Test squeezing with custom replacement strings."""
89+ self .assertEqual (squeeze ('hello world' , 8 , '..' ), 'hel..rld' )
90+ self .assertEqual (squeeze ('hello world' , 7 , '..' ), 'he..rld' )
91+ self .assertEqual (squeeze ('hello world' , 9 , '---' ), 'hel---rld' )
92+ self .assertEqual (squeeze ('hello world' , 10 , 'XX' ), 'hellXXorld' )
93+
94+ def test_squeeze_with_single_character_replacement (self ) -> None :
95+ """Test squeezing with single character replacement."""
96+ self .assertEqual (squeeze ('hello world' , 5 , '*' ), 'he*ld' )
97+ self .assertEqual (squeeze ('hello world' , 6 , '*' ), 'he*rld' )
98+ self .assertEqual (squeeze ('hello world' , 7 , '*' ), 'hel*rld' )
99+
100+ def test_squeeze_with_empty_replacement (self ) -> None :
101+ """Test squeezing with empty replacement string."""
102+ self .assertEqual (squeeze ('hello world' , 5 , '' ), 'herld' )
103+ self .assertEqual (squeeze ('hello world' , 6 , '' ), 'helrld' )
104+ self .assertEqual (squeeze ('hello world' , 7 , '' ), 'helorld' )
105+
106+ def test_squeeze_replacement_equals_target_size (self ) -> None :
107+ """Test when replacement string equals the target size."""
108+ self .assertEqual (squeeze ('hello world' , 4 , '....' ), '....' )
109+ self .assertEqual (squeeze ('hello world' , 3 , '***' ), '***' )
110+
111+ def test_squeeze_very_short_target_sizes (self ) -> None :
112+ """Test edge cases with very short target sizes."""
113+ self .assertEqual (squeeze ('hello world' , 5 , '.' ), 'he.ld' )
114+ self .assertEqual (squeeze ('hello world' , 6 , '.' ), 'he.rld' )
115+ self .assertEqual (squeeze ('hello world' , 1 , 'X' ), 'X' )
116+
117+ def test_squeeze_with_long_text (self ) -> None :
118+ """Test squeezing with very long text."""
119+ long_text = 'a' * 100
120+ result = squeeze (long_text , 10 , '...' )
121+ self .assertEqual (len (result ), 10 )
122+ self .assertEqual (result , 'aaa...aaaa' )
123+
124+ # Test with different replacement
125+ result2 = squeeze (long_text , 8 , '--' )
126+ self .assertEqual (len (result2 ), 8 )
127+ self .assertEqual (result2 , 'aaa--aaa' )
128+
129+ def test_squeeze_size_distribution_even (self ) -> None :
130+ """Test size distribution when remaining space is even."""
131+ # size=8, replacement="--" (len=2), remaining=6, left=3, right=3
132+ self .assertEqual (squeeze ('abcdefghijk' , 8 , '--' ), 'abc--ijk' )
133+ # size=10, replacement="...." (len=4), remaining=6, left=3, right=3
134+ self .assertEqual (squeeze ('abcdefghijk' , 10 , '....' ), 'abc....ijk' )
135+
136+ def test_squeeze_size_distribution_odd (self ) -> None :
137+ """Test size distribution when remaining space is odd."""
138+ # size=9, replacement="--" (len=2), remaining=7, left=3, right=4
139+ self .assertEqual (squeeze ('abcdefghijk' , 9 , '--' ), 'abc--hijk' )
140+ # size=11, replacement="..." (len=3), remaining=8, left=4, right=4
141+ self .assertEqual (squeeze ('abcdefghijk' , 11 , '...' ), 'abcdefghijk' )
142+
143+ def test_squeeze_raises_error_when_replacement_too_long (self ) -> None :
144+ """Test that ValueError is raised when replacement is longer than target size."""
145+ with self .assertRaises (ValueError ) as context :
146+ squeeze ('hello world' , 3 , ' ... ' )
147+ self .assertIn ('size = 3 < len(replacement) = 5' , str (context .exception ))
148+
149+ with self .assertRaises (ValueError ) as context :
150+ squeeze ('hello world' , 2 , 'abc' )
151+ self .assertIn ('size = 2 < len(replacement) = 3' , str (context .exception ))
152+
153+ with self .assertRaises (ValueError ) as context :
154+ squeeze ('hello world' , 1 , 'ab' )
155+ self .assertIn ('size = 1 < len(replacement) = 2' , str (context .exception ))
156+
157+ def test_squeeze_error_when_replacement_long_but_no_squeeze_needed (self ) -> None :
158+ """Test that no error is raised when replacement is long but text doesn't need squeezing."""
159+ # Text is shorter than size, so no squeezing would occur,
160+ # yet, the replacement is longer than the requested size, so error is raised
161+ with self .assertRaises (ValueError ) as context :
162+ self .assertEqual (squeeze ('abc' , 10 , 'very long replacement' ), 'abc' )
163+ self .assertIn ('size = 10 < len(replacement) = 21' , str (context .exception ))
164+
165+ with self .assertRaises (ValueError ) as context :
166+ self .assertEqual (squeeze ('' , 3 , 'abcd' ), '' )
167+ self .assertIn ('size = 3 < len(replacement) = 4' , str (context .exception ))
168+
169+
170+ if __name__ == '__main__' :
171+ unittest .main ()
0 commit comments