1414import com .sun .net .httpserver .HttpExchange ;
1515import com .sun .net .httpserver .HttpPrincipal ;
1616
17+ import org .elasticsearch .common .Randomness ;
1718import org .elasticsearch .common .Strings ;
1819import org .elasticsearch .common .bytes .BytesArray ;
1920import org .elasticsearch .common .bytes .BytesReference ;
2829import java .net .InetSocketAddress ;
2930import java .net .URI ;
3031import java .nio .charset .StandardCharsets ;
32+ import java .util .ArrayList ;
3133import java .util .List ;
3234import java .util .Objects ;
3335
@@ -45,63 +47,80 @@ public void testRejectsBadUri() {
4547 );
4648 }
4749
50+ private static void assertListObjectsResponse (
51+ S3HttpHandler handler ,
52+ @ Nullable String prefix ,
53+ @ Nullable String delimiter ,
54+ String expectedResponse
55+ ) {
56+ final var queryParts = new ArrayList <String >(3 );
57+ if (prefix != null ) {
58+ queryParts .add ("prefix=" + prefix );
59+ }
60+ if (delimiter != null ) {
61+ queryParts .add ("delimiter=" + delimiter );
62+ }
63+ if (randomBoolean ()) {
64+ queryParts .add ("list-type=2" );
65+ }
66+ Randomness .shuffle (queryParts );
67+
68+ final var requestUri = "/bucket" + randomFrom ("" , "/" ) + (queryParts .isEmpty () ? "" : "?" + String .join ("&" , queryParts ));
69+ assertEquals ("GET " + requestUri , new TestHttpResponse (RestStatus .OK , expectedResponse ), handleRequest (handler , "GET" , requestUri ));
70+ }
71+
4872 public void testSimpleObjectOperations () {
4973 final var handler = new S3HttpHandler ("bucket" , "path" );
5074
5175 assertEquals (RestStatus .NOT_FOUND , handleRequest (handler , "GET" , "/bucket/path/blob" ).status ());
5276
53- assertEquals (
54- new TestHttpResponse (RestStatus .OK , """
55- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix></ListBucketResult>""" ),
56- handleRequest (handler , "GET" , "/bucket/?prefix=" )
57- );
77+ assertListObjectsResponse (handler , "" , null , """
78+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix><IsTruncated>false</IsTruncated>\
79+ </ListBucketResult>""" );
5880
5981 final var body = randomAlphaOfLength (50 );
6082 assertEquals (RestStatus .OK , handleRequest (handler , "PUT" , "/bucket/path/blob" , body ).status ());
6183 assertEquals (new TestHttpResponse (RestStatus .OK , body ), handleRequest (handler , "GET" , "/bucket/path/blob" ));
6284
63- assertEquals ( new TestHttpResponse ( RestStatus . OK , """
64- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix>\
85+ assertListObjectsResponse ( handler , "" , null , """
86+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix><IsTruncated>false</IsTruncated> \
6587 <Contents><Key>path/blob</Key><Size>50</Size></Contents>\
66- </ListBucketResult>""" ), handleRequest ( handler , "GET" , "/bucket/?prefix=" )) ;
88+ </ListBucketResult>""" );
6789
68- assertEquals ( new TestHttpResponse ( RestStatus . OK , """
69- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix>path/</Prefix>\
90+ assertListObjectsResponse ( handler , "path/" , null , """
91+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix>path/</Prefix><IsTruncated>false</IsTruncated> \
7092 <Contents><Key>path/blob</Key><Size>50</Size></Contents>\
71- </ListBucketResult>""" ), handleRequest ( handler , "GET" , "/bucket/?prefix=path/" )) ;
93+ </ListBucketResult>""" );
7294
73- assertEquals (
74- new TestHttpResponse (RestStatus .OK , """
75- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix>path/other</Prefix></ListBucketResult>""" ),
76- handleRequest (handler , "GET" , "/bucket/?prefix=path/other" )
77- );
95+ assertListObjectsResponse (handler , "path/other" , null , """
96+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix>path/other</Prefix><IsTruncated>false</IsTruncated>\
97+ </ListBucketResult>""" );
7898
7999 assertEquals (RestStatus .OK , handleRequest (handler , "PUT" , "/bucket/path/subpath1/blob" , randomAlphaOfLength (50 )).status ());
80100 assertEquals (RestStatus .OK , handleRequest (handler , "PUT" , "/bucket/path/subpath2/blob" , randomAlphaOfLength (50 )).status ());
81- assertEquals (new TestHttpResponse (RestStatus .OK , """
82- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix>path/</Prefix>\
83- <Delimiter>/</Delimiter><Contents><Key>path/blob</Key><Size>50</Size></Contents>\
101+ assertListObjectsResponse (handler , "path/" , "/" , """
102+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult>\
103+ <Prefix>path/</Prefix><Delimiter>/</Delimiter><IsTruncated>false</IsTruncated>\
104+ <Contents><Key>path/blob</Key><Size>50</Size></Contents>\
84105 <CommonPrefixes><Prefix>path/subpath1/</Prefix></CommonPrefixes>\
85106 <CommonPrefixes><Prefix>path/subpath2/</Prefix></CommonPrefixes>\
86- </ListBucketResult>""" ), handleRequest ( handler , "GET" , "/bucket/?delimiter=/&prefix=path/" )) ;
107+ </ListBucketResult>""" );
87108
88109 assertEquals (RestStatus .OK , handleRequest (handler , "DELETE" , "/bucket/path/blob" ).status ());
89110 assertEquals (RestStatus .NO_CONTENT , handleRequest (handler , "DELETE" , "/bucket/path/blob" ).status ());
90111
91- assertEquals ( new TestHttpResponse ( RestStatus . OK , """
92- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix>\
112+ assertListObjectsResponse ( handler , "" , null , """
113+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix><IsTruncated>false</IsTruncated> \
93114 <Contents><Key>path/subpath1/blob</Key><Size>50</Size></Contents>\
94115 <Contents><Key>path/subpath2/blob</Key><Size>50</Size></Contents>\
95- </ListBucketResult>""" ), handleRequest ( handler , "GET" , "/bucket/?prefix=" )) ;
116+ </ListBucketResult>""" );
96117
97118 assertEquals (RestStatus .OK , handleRequest (handler , "DELETE" , "/bucket/path/subpath1/blob" ).status ());
98119 assertEquals (RestStatus .OK , handleRequest (handler , "DELETE" , "/bucket/path/subpath2/blob" ).status ());
99120
100- assertEquals (
101- new TestHttpResponse (RestStatus .OK , """
102- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix></ListBucketResult>""" ),
103- handleRequest (handler , "GET" , "/bucket/?prefix=" )
104- );
121+ assertListObjectsResponse (handler , "" , null , """
122+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix><IsTruncated>false</IsTruncated>\
123+ </ListBucketResult>""" );
105124 }
106125
107126 public void testGetWithBytesRange () {
@@ -216,10 +235,10 @@ public void testSingleMultipartUpload() {
216235 </CompleteMultipartUpload>""" , part1Etag , part2Etag ))
217236 );
218237
219- assertEquals ( new TestHttpResponse ( RestStatus . OK , """
220- <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix>\
238+ assertListObjectsResponse ( handler , "" , null , """
239+ <?xml version="1.0" encoding="UTF-8"?><ListBucketResult><Prefix></Prefix><IsTruncated>false</IsTruncated> \
221240 <Contents><Key>path/blob</Key><Size>100</Size></Contents>\
222- </ListBucketResult>""" ), handleRequest ( handler , "GET" , "/bucket/?prefix=" )) ;
241+ </ListBucketResult>""" );
223242
224243 assertEquals (new TestHttpResponse (RestStatus .OK , part1 + part2 ), handleRequest (handler , "GET" , "/bucket/path/blob" ));
225244
0 commit comments