16
16
package software .amazon .awssdk .transfer .s3 .config ;
17
17
18
18
import static org .assertj .core .api .Assertions .assertThat ;
19
+ import static org .junit .jupiter .api .Assertions .assertThrows ;
19
20
21
+ import java .util .function .Function ;
20
22
import java .util .stream .Stream ;
23
+ import org .junit .jupiter .api .DisplayName ;
21
24
import org .junit .jupiter .params .ParameterizedTest ;
22
25
import org .junit .jupiter .params .provider .Arguments ;
23
26
import org .junit .jupiter .params .provider .MethodSource ;
@@ -38,4 +41,168 @@ public static Stream<Arguments> s3Objects() {
38
41
void allObjectsFilter_shouldWork (S3Object s3Object , boolean result ) {
39
42
assertThat (DownloadFilter .allObjects ().test (s3Object )).isEqualTo (result );
40
43
}
44
+
45
+ private static Stream <Arguments > filterOperationTestCases () {
46
+ Function <S3Object , DownloadFilter > folder1OrFolder3Filter = s3Object -> {
47
+ DownloadFilter folder1 = obj -> obj .key ().startsWith ("folder1" );
48
+ DownloadFilter folder3 = obj -> obj .key ().startsWith ("folder3" );
49
+ return folder1 .or (folder3 );
50
+ };
51
+
52
+ Function <S3Object , DownloadFilter > txtAndLargeSizeFilter = s3Object -> {
53
+ DownloadFilter txtFilter = obj -> obj .key ().endsWith (".txt" );
54
+ DownloadFilter sizeFilter = obj -> obj .size () > 1000L ;
55
+ return txtFilter .and (sizeFilter );
56
+ };
57
+
58
+ Function <S3Object , DownloadFilter > notFolder1Filter = s3Object -> {
59
+ DownloadFilter folder1 = obj -> obj .key ().startsWith ("folder1" );
60
+ return folder1 .negate ();
61
+ };
62
+
63
+ Function <S3Object , DownloadFilter > notLargeSizeFilter = s3Object -> {
64
+ DownloadFilter largeSize = obj -> obj .size () > 1000L ;
65
+ return largeSize .negate ();
66
+ };
67
+
68
+ Function <S3Object , DownloadFilter > complexFilter = s3Object -> {
69
+ DownloadFilter folder1 = obj -> obj .key ().startsWith ("folder1" );
70
+ DownloadFilter folder3 = obj -> obj .key ().startsWith ("folder3" );
71
+ DownloadFilter sizeFilter = obj -> obj .size () > 1000L ;
72
+ return folder1 .or (folder3 ).and (sizeFilter );
73
+ };
74
+ Function <S3Object , DownloadFilter > nullParameterFilter = s3Object -> {
75
+ DownloadFilter baseFilter = obj -> obj .key ().startsWith ("folder1" );
76
+ return s -> {
77
+ assertThrows (NullPointerException .class ,
78
+ () -> baseFilter .or (null ),
79
+ "or() should throw NullPointerException when other is null" );
80
+ assertThrows (NullPointerException .class ,
81
+ () -> baseFilter .and (null ),
82
+ "and() should throw NullPointerException when other is null" );
83
+ return true ; // Return value doesn't matter as we're testing for exceptions
84
+ };
85
+ };
86
+
87
+
88
+ return Stream .of (
89
+ // OR operation tests
90
+ Arguments .of (
91
+ "OR: folder1/test.txt matches (folder1 OR folder3)" ,
92
+ S3Object .builder ().key ("folder1/test.txt" ).size (2000L ).build (),
93
+ folder1OrFolder3Filter ,
94
+ true
95
+ ),
96
+ Arguments .of (
97
+ "OR: folder3/test.txt matches (folder1 OR folder3)" ,
98
+ S3Object .builder ().key ("folder3/test.txt" ).size (2000L ).build (),
99
+ folder1OrFolder3Filter ,
100
+ true
101
+ ),
102
+ Arguments .of (
103
+ "OR: folder2/test.txt does not match (folder1 OR folder3)" ,
104
+ S3Object .builder ().key ("folder2/test.txt" ).size (2000L ).build (),
105
+ folder1OrFolder3Filter ,
106
+ false
107
+ ),
108
+
109
+ // AND operation tests
110
+ Arguments .of (
111
+ "AND: large .txt file matches (.txt AND size > 1000)" ,
112
+ S3Object .builder ().key ("folder1/test.txt" ).size (2000L ).build (),
113
+ txtAndLargeSizeFilter ,
114
+ true
115
+ ),
116
+ Arguments .of (
117
+ "AND: small .txt file does not match (.txt AND size > 1000)" ,
118
+ S3Object .builder ().key ("folder1/test.txt" ).size (500L ).build (),
119
+ txtAndLargeSizeFilter ,
120
+ false
121
+ ),
122
+ Arguments .of (
123
+ "AND: large .pdf file does not match (.txt AND size > 1000)" ,
124
+ S3Object .builder ().key ("folder1/test.pdf" ).size (2000L ).build (),
125
+ txtAndLargeSizeFilter ,
126
+ false
127
+ ),
128
+
129
+ // NEGATE operation tests
130
+ Arguments .of (
131
+ "NEGATE: folder1 file does not match NOT(folder1)" ,
132
+ S3Object .builder ().key ("folder1/test.txt" ).size (1000L ).build (),
133
+ notFolder1Filter ,
134
+ false
135
+ ),
136
+ Arguments .of (
137
+ "NEGATE: folder2 file matches NOT(folder1)" ,
138
+ S3Object .builder ().key ("folder2/test.txt" ).size (1000L ).build (),
139
+ notFolder1Filter ,
140
+ true
141
+ ),
142
+ Arguments .of (
143
+ "NEGATE: large file does not match NOT(size > 1000)" ,
144
+ S3Object .builder ().key ("test.txt" ).size (2000L ).build (),
145
+ notLargeSizeFilter ,
146
+ false
147
+ ),
148
+ Arguments .of (
149
+ "NEGATE: small file matches NOT(size > 1000)" ,
150
+ S3Object .builder ().key ("test.txt" ).size (500L ).build (),
151
+ notLargeSizeFilter ,
152
+ true
153
+ ),
154
+
155
+ // Complex chained operations
156
+ Arguments .of (
157
+ "COMPLEX: large file in folder1 matches ((folder1 OR folder3) AND size > 1000)" ,
158
+ S3Object .builder ().key ("folder1/test.txt" ).size (2000L ).build (),
159
+ complexFilter ,
160
+ true
161
+ ),
162
+ Arguments .of (
163
+ "COMPLEX: small file in folder1 does not match ((folder1 OR folder3) AND size > 1000)" ,
164
+ S3Object .builder ().key ("folder1/test.txt" ).size (500L ).build (),
165
+ complexFilter ,
166
+ false
167
+ ),
168
+ Arguments .of (
169
+ "COMPLEX: large file in folder2 does not match ((folder1 OR folder3) AND size > 1000)" ,
170
+ S3Object .builder ().key ("folder2/test.txt" ).size (2000L ).build (),
171
+ complexFilter ,
172
+ false
173
+ ),
174
+ Arguments .of (
175
+ "COMPLEX: large file in folder3 matches ((folder1 OR folder3) AND size > 1000)" ,
176
+ S3Object .builder ().key ("folder3/test.txt" ).size (2000L ).build (),
177
+ complexFilter ,
178
+ true
179
+ ),
180
+ // NullPointerException
181
+ Arguments .of (
182
+ "NULL: or/and with null parameter should throw NullPointerException" ,
183
+ S3Object .builder ().key ("folder1/test.txt" ).size (1000L ).build (),
184
+ nullParameterFilter ,
185
+ true
186
+ )
187
+
188
+ );
189
+ }
190
+
191
+ @ ParameterizedTest
192
+ @ MethodSource ("filterOperationTestCases" )
193
+ @ DisplayName ("Test DownloadFilter operations (AND, OR, NEGATE)" )
194
+ void testFilterOperations (String scenario , S3Object s3Object ,
195
+ Function <S3Object , DownloadFilter > filterFactory ,
196
+ boolean expectedResult ) {
197
+ // Given
198
+ DownloadFilter filter = filterFactory .apply (s3Object );
199
+
200
+ // When
201
+ boolean actualResult = filter .test (s3Object );
202
+
203
+ // Then
204
+ assertThat (actualResult )
205
+ .as (scenario )
206
+ .isEqualTo (expectedResult );
207
+ }
41
208
}
0 commit comments