1 package voldemort
.server
.rest
;
3 import static org
.junit
.Assert
.assertEquals
;
4 import static org
.junit
.Assert
.fail
;
6 import java
.io
.BufferedReader
;
7 import java
.io
.IOException
;
8 import java
.io
.InputStreamReader
;
9 import java
.io
.OutputStream
;
10 import java
.net
.HttpURLConnection
;
13 import org
.apache
.commons
.codec
.binary
.Base64
;
14 import org
.apache
.log4j
.Logger
;
15 import org
.junit
.AfterClass
;
16 import org
.junit
.BeforeClass
;
17 import org
.junit
.Test
;
19 import voldemort
.coordinator
.CoordinatorUtils
;
20 import voldemort
.server
.VoldemortConfig
;
21 import voldemort
.server
.VoldemortServer
;
22 import voldemort
.versioning
.VectorClock
;
24 public class RestServerProtocolTests
{
26 private static String storeNameStr
;
27 private static String key1
;
28 private static String urlStr
;
29 private static String value1
;
30 private static String contentType
;
31 private static long timeOut
, originTime
;
32 private static int routingType
;
33 private static VectorClock vectorClock
;
34 private static String eTag
;
35 private static VoldemortServer server
;
36 private static VoldemortConfig config
;
37 private static Logger logger
= Logger
.getLogger(RestServerProtocolTests
.class);
40 * TODO REST-Server: Hard coded storeName and urlStr. They must be retrieved
45 public static void oneTimeSetUp() {
46 storeNameStr
= "test";
47 urlStr
= "http://localhost:8081/";
48 config
= VoldemortConfig
.loadFromVoldemortHome("config/single_node_cluster/");
49 key1
= "The longest key ";
50 vectorClock
= new VectorClock();
51 vectorClock
.incrementVersion(config
.getNodeId(), System
.currentTimeMillis());
52 eTag
= CoordinatorUtils
.getSerializedVectorClock(vectorClock
);
53 value1
= "The longest value";
56 originTime
= System
.currentTimeMillis();
58 server
= new VoldemortServer(config
);
59 if(!server
.isStarted())
61 System
.out
.println("********************Starting REST Server********************");
65 public static void oneTimeCleanUp() {
66 if(server
!= null && server
.isStarted()) {
71 public HttpURLConnection
doPut(String url
,
80 String contentLength
) throws IOException
{
82 HttpURLConnection conn
= createConnection(url
,
89 conn
.setDoOutput(true);
90 if(vectorClock
!= null) {
91 conn
.setRequestProperty(RestMessageHeaders
.X_VOLD_VECTOR_CLOCK
, vectorClock
);
93 if(ContentType
!= null) {
94 conn
.setRequestProperty("Content-Type", ContentType
);
96 if(contentLength
!= null) {
97 conn
.setRequestProperty("Content-Length", contentLength
);
101 OutputStream out
= conn
.getOutputStream();
102 out
.write(value
.getBytes());
108 public HttpURLConnection
doDelete(String url
,
114 String vectorClock
) throws IOException
{
115 HttpURLConnection conn
= createConnection(url
,
122 if(vectorClock
!= null) {
123 conn
.setRequestProperty(RestMessageHeaders
.X_VOLD_VECTOR_CLOCK
, vectorClock
);
129 public HttpURLConnection
doGet(String url
,
134 String routingType
) throws IOException
{
136 HttpURLConnection conn
= createConnection(url
,
147 * Creates a basic put/get/delete request with common required headers.
157 * @throws IOException
159 public HttpURLConnection
createConnection(String urlString
,
165 String method
) throws IOException
{
167 HttpURLConnection conn
= null;
169 String urlStr
= urlString
;
170 String base64Key
= "";
171 if(storeName
!= null) {
172 urlStr
+= storeName
+ "/";
175 base64Key
= new String(Base64
.encodeBase64(key
.getBytes()));
176 url
= new URL(urlStr
+ base64Key
);
178 url
= new URL(urlStr
);
180 conn
= (HttpURLConnection
) url
.openConnection();
181 conn
.setRequestMethod(method
);
182 conn
.setDoInput(true);
184 if(originTime
!= null) {
185 conn
.setRequestProperty(RestMessageHeaders
.X_VOLD_REQUEST_ORIGIN_TIME_MS
,
186 String
.valueOf(originTime
));
188 if(timeOut
!= null) {
189 conn
.setRequestProperty(RestMessageHeaders
.X_VOLD_REQUEST_TIMEOUT_MS
,
190 String
.valueOf(timeOut
));
192 if(routingType
!= null) {
193 conn
.setRequestProperty(RestMessageHeaders
.X_VOLD_ROUTING_TYPE_CODE
,
194 String
.valueOf(routingType
));
200 public void readErrorMessageFromResponse(HttpURLConnection conn
) throws IOException
{
201 BufferedReader bufferedReader
;
202 bufferedReader
= new BufferedReader(new InputStreamReader(conn
.getErrorStream()));
203 StringBuilder stringBuilder
= new StringBuilder();
205 while((line
= bufferedReader
.readLine()) != null) {
206 stringBuilder
.append(line
);
208 bufferedReader
.close();
209 logger
.info(stringBuilder
.toString());
213 public void testMissingRoutingType() {
214 logger
.info("********** Testing missing routing type **********");
215 HttpURLConnection conn
= null;
216 int responseCode
= -1;
222 String
.valueOf(originTime
),
223 String
.valueOf(timeOut
),
227 String
.valueOf(value1
.getBytes().length
));
229 responseCode
= conn
.getResponseCode();
230 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
231 readErrorMessageFromResponse(conn
);
232 } catch(IOException e1
) {
233 e1
.printStackTrace();
235 assertEquals(responseCode
, 400);
240 public void testInvalidRoutingType() {
241 logger
.info("********** Testing invalid routing type **********");
242 HttpURLConnection conn
= null;
243 int responseCode
= -1;
248 String
.valueOf(originTime
),
249 String
.valueOf(timeOut
),
252 responseCode
= conn
.getResponseCode();
253 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
254 readErrorMessageFromResponse(conn
);
255 } catch(IOException e1
) {
256 e1
.printStackTrace();
258 assertEquals(responseCode
, 400);
263 public void testNonNumberRoutingType() {
264 logger
.info("********** Testing non number Routing Type **********");
265 HttpURLConnection conn
= null;
266 int responseCode
= -1;
268 conn
= doDelete(urlStr
,
271 String
.valueOf(originTime
),
272 String
.valueOf(timeOut
),
276 responseCode
= conn
.getResponseCode();
277 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
278 readErrorMessageFromResponse(conn
);
279 } catch(IOException e1
) {
280 e1
.printStackTrace();
282 assertEquals(responseCode
, 400);
287 public void testMissingTimeOut() {
288 logger
.info("********** Testing missing time out **********");
289 HttpURLConnection conn
= null;
290 int responseCode
= -1;
296 String
.valueOf(originTime
),
298 String
.valueOf(routingType
),
301 String
.valueOf(value1
.getBytes().length
));
302 responseCode
= conn
.getResponseCode();
303 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
304 readErrorMessageFromResponse(conn
);
305 } catch(IOException e
) {
308 assertEquals(responseCode
, 400);
313 public void testNonNumberTimeOut() {
314 logger
.info("********** Testing non number time out **********");
315 HttpURLConnection conn
= null;
316 int responseCode
= -1;
321 String
.valueOf(originTime
),
323 String
.valueOf(routingType
));
324 responseCode
= conn
.getResponseCode();
325 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
326 readErrorMessageFromResponse(conn
);
327 } catch(IOException e
) {
330 assertEquals(responseCode
, 400);
335 public void testMissingTimeStamp() {
336 logger
.info("********** Testing missing time stamp **********");
337 HttpURLConnection conn
= null;
338 int responseCode
= -1;
340 conn
= doDelete(urlStr
,
344 String
.valueOf(timeOut
),
345 String
.valueOf(routingType
),
347 responseCode
= conn
.getResponseCode();
348 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
349 readErrorMessageFromResponse(conn
);
350 } catch(IOException e
) {
353 assertEquals(responseCode
, 400);
358 public void testNonNumberTimeStamp() {
359 logger
.info("********** Testing non number time out **********");
360 HttpURLConnection conn
= null;
361 int responseCode
= -1;
368 String
.valueOf(timeOut
),
369 String
.valueOf(routingType
),
372 String
.valueOf(value1
.getBytes().length
));
373 responseCode
= conn
.getResponseCode();
374 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
375 readErrorMessageFromResponse(conn
);
376 } catch(IOException e
) {
379 assertEquals(responseCode
, 400);
384 public void testMissingKey() {
385 logger
.info("********** Testing missing key **********");
386 HttpURLConnection conn
= null;
387 int responseCode
= -1;
392 String
.valueOf(originTime
),
393 String
.valueOf(timeOut
),
394 String
.valueOf(routingType
));
395 responseCode
= conn
.getResponseCode();
396 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
397 readErrorMessageFromResponse(conn
);
398 } catch(IOException e
) {
401 assertEquals(responseCode
, 400);
406 public void testMissingStoreName() {
407 logger
.info("********** Testing missing store name **********");
408 HttpURLConnection conn
= null;
409 int responseCode
= -1;
411 conn
= doDelete(urlStr
,
414 String
.valueOf(originTime
),
415 String
.valueOf(timeOut
),
416 String
.valueOf(routingType
),
418 responseCode
= conn
.getResponseCode();
419 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
420 readErrorMessageFromResponse(conn
);
421 } catch(IOException e
) {
424 assertEquals(responseCode
, 400);
429 public void testInvalidStoreName() {
430 logger
.info("********** Testing invalid store name **********");
431 HttpURLConnection conn
= null;
432 int responseCode
= -1;
437 String
.valueOf(originTime
),
438 String
.valueOf(timeOut
),
439 String
.valueOf(routingType
));
440 responseCode
= conn
.getResponseCode();
441 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
442 readErrorMessageFromResponse(conn
);
443 } catch(IOException e
) {
446 assertEquals(responseCode
, 400);
451 public void testMissingVectorClock() {
452 logger
.info("********** Testing missing vector clock **********");
453 HttpURLConnection conn
= null;
454 int responseCode
= -1;
460 String
.valueOf(originTime
),
461 String
.valueOf(timeOut
),
462 String
.valueOf(routingType
),
465 String
.valueOf(value1
.getBytes().length
));
466 responseCode
= conn
.getResponseCode();
467 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
468 readErrorMessageFromResponse(conn
);
469 } catch(IOException e
) {
472 assertEquals(responseCode
, 400);
477 public void testInvalidVectorClock() {
478 logger
.info("********** Testing invalid vector clock **********");
479 HttpURLConnection conn
= null;
480 int responseCode
= -1;
482 conn
= doDelete(urlStr
,
485 String
.valueOf(originTime
),
486 String
.valueOf(timeOut
),
487 String
.valueOf(routingType
),
489 responseCode
= conn
.getResponseCode();
490 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
491 readErrorMessageFromResponse(conn
);
492 } catch(IOException e
) {
495 assertEquals(responseCode
, 400);
500 public void testGetWithNonExistingKey() {
501 logger
.info("********** Testing get with non existing key **********");
502 HttpURLConnection conn
= null;
503 int responseCode
= -1;
508 String
.valueOf(originTime
),
509 String
.valueOf(timeOut
),
510 String
.valueOf(routingType
));
511 responseCode
= conn
.getResponseCode();
512 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
513 readErrorMessageFromResponse(conn
);
514 } catch(IOException e
) {
517 assertEquals(responseCode
, 404);
522 public void testGetAllWithNonExistingKey() {
523 logger
.info("********** Testing get all with all non existing keys **********");
524 HttpURLConnection conn
= null;
525 int responseCode
= -1;
528 "non existing key1, non existing key2",
530 String
.valueOf(originTime
),
531 String
.valueOf(timeOut
),
532 String
.valueOf(routingType
));
533 responseCode
= conn
.getResponseCode();
534 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
535 readErrorMessageFromResponse(conn
);
536 } catch(IOException e
) {
539 assertEquals(responseCode
, 404);
544 public void testObsoleteVersionException() throws IOException
{
545 logger
.info("********** Testing obsolete version exception **********");
548 deleteKeysCreated(key1
, eTag
);
550 HttpURLConnection conn
= null;
551 int responseCode
= -1;
557 String
.valueOf(originTime
),
558 String
.valueOf(timeOut
),
559 String
.valueOf(routingType
),
562 String
.valueOf(value1
.getBytes().length
));
563 responseCode
= conn
.getResponseCode();
564 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
565 if(responseCode
!= 200 && responseCode
!= 201) {
566 fail("Initial put failed");
573 String
.valueOf(originTime
),
574 String
.valueOf(timeOut
),
575 String
.valueOf(routingType
),
578 String
.valueOf(value1
.getBytes().length
));
579 responseCode
= conn
.getResponseCode();
580 logger
.info("Response Code: " + responseCode
+ " Message: "
581 + conn
.getResponseMessage());
582 readErrorMessageFromResponse(conn
);
584 } catch(IOException e
) {
587 assertEquals(responseCode
, 412);
591 deleteKeysCreated(key1
, eTag
);
595 public void testDeleteWithNonExistingKey() {
596 logger
.info("********** Testing delete non existing key **********");
597 HttpURLConnection conn
= null;
598 int responseCode
= -1;
600 conn
= doDelete(urlStr
,
603 String
.valueOf(originTime
),
604 String
.valueOf(timeOut
),
605 String
.valueOf(routingType
),
607 responseCode
= conn
.getResponseCode();
608 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
609 readErrorMessageFromResponse(conn
);
611 } catch(IOException e
) {
614 assertEquals(responseCode
, 404);
619 public void testDeleteLowerVersion() throws IOException
{
620 logger
.info("********** Testing delete lower version **********");
622 deleteKeysCreated(key1
, eTag
);
624 HttpURLConnection conn
= null;
625 int responseCode
= -1;
632 String
.valueOf(originTime
),
633 String
.valueOf(timeOut
),
634 String
.valueOf(routingType
),
637 String
.valueOf(value1
.getBytes().length
));
638 responseCode
= conn
.getResponseCode();
639 logger
.info("Response Code: " + responseCode
+ " Message: " + conn
.getResponseMessage());
641 if(responseCode
!= 200 && responseCode
!= 201) {
642 fail("Initial put failed");
644 VectorClock vc
= vectorClock
.incremented(config
.getNodeId(),
645 System
.currentTimeMillis());
646 eTag2
= CoordinatorUtils
.getSerializedVectorClock(vc
);
647 String value2
= "The next longest value";
652 String
.valueOf(originTime
),
653 String
.valueOf(timeOut
),
654 String
.valueOf(routingType
),
657 String
.valueOf(value2
.getBytes().length
));
658 responseCode
= conn
.getResponseCode();
659 logger
.info("Response Code: " + responseCode
+ " Message: "
660 + conn
.getResponseMessage());
662 if(responseCode
!= 201) {
663 fail("Second put failed");
665 conn
= doDelete(urlStr
,
668 String
.valueOf(originTime
),
669 String
.valueOf(timeOut
),
670 String
.valueOf(routingType
),
672 responseCode
= conn
.getResponseCode();
673 logger
.info("Response Code: " + responseCode
+ " Message: "
674 + conn
.getResponseMessage());
675 readErrorMessageFromResponse(conn
);
678 } catch(IOException e
) {
681 assertEquals(responseCode
, 404);
684 // cleanUP specific to this test case
685 deleteKeysCreated(key1
, eTag
);
686 deleteKeysCreated(key1
, eTag2
);
691 public void deleteKeysCreated(String key
, String eTag
) throws IOException
{
692 HttpURLConnection conn
= null;
693 conn
= doDelete(urlStr
,
696 String
.valueOf(originTime
),
697 String
.valueOf(timeOut
),
698 String
.valueOf(routingType
),
700 conn
.getResponseCode();