package org.swisspush.reststorage; import io.vertx.ext.unit.Async; import io.vertx.ext.unit.TestContext; import io.vertx.ext.unit.junit.VertxUnitRunner; import org.junit.Test; import org.junit.runner.RunWith; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import static com.jayway.awaitility.Awaitility.await; import static com.jayway.awaitility.Duration.TWO_SECONDS; import static com.jayway.restassured.RestAssured.*; import static org.hamcrest.Matchers.*; import static org.hamcrest.core.IsEqual.equalTo; @RunWith(VertxUnitRunner.class) public class ExpirationTest extends AbstractTestCase { @Test public void testPutInvalidExpireFloat(TestContext context) { Async async = context.async(); given(). header("x-expire-after", "1.22"). body("{ \"foo\": \"bar1\" }"). when(). put("expireisfloat"). then(). assertThat().statusCode(400); when().get("expireaftertwoseconds").then().assertThat().statusCode(404); async.complete(); } @Test public void testPutInvalidExpireNaN(TestContext context) { Async async = context.async(); given(). header("x-expire-after", "asdfasdf"). body("{ \"foo\": \"bar1\" }"). when(). put("invalidExpireNan"). then(). assertThat().statusCode(400); when().get("invalidExpireNan").then().assertThat().statusCode(404); async.complete(); } @Test public void testPutExpireAfterOneSecond(TestContext context) { Async async = context.async(); given(). header("x-expire-after", "1"). body("{ \"foo\": \"bar1\" }"). when(). put("expireaftertwoseconds"). then(). assertThat().statusCode(200); await().atMost(TWO_SECONDS).until(new Callable<Integer>() { public Integer call() throws Exception { return get("expireaftertwoseconds").statusCode(); } }, equalTo(404)); async.complete(); } @Test public void testPutAfterExpiration(TestContext context) { Async async = context.async(); given(). header("x-expire-after", "1"). body("{ \"foo\": \"bar1\" }"). when(). put("putafterexpiration"). then(). assertThat().statusCode(200); await().atMost(3, TimeUnit.SECONDS).until(new Callable<Integer>() { public Integer call() throws Exception { return get("putafterexpiration").statusCode(); } }, equalTo(404)); given(). header("x-expire-after", "10"). body("{ \"foo\": \"bar2\" }"). when(). put("putafterexpiration"). then(). assertThat().statusCode(200); when().get("putafterexpiration").then().statusCode(200).body("foo", equalTo("bar2")); async.complete(); } @Test public void testPutAfterImmediateExpiration(TestContext context) { Async async = context.async(); given(). header("x-expire-after", "0"). body("{ \"foo\": \"bar1\" }"). when(). put("expireimmediatly"). then(). assertThat().statusCode(200); await().atMost(TWO_SECONDS).until(() -> get("expireimmediatly").statusCode(), equalTo(404)); given(). header("x-expire-after", "10"). body("{ \"foo\": \"bar2\" }"). when(). put("expireimmediatly"). then(). assertThat().statusCode(200); when().get("/expireimmediatly").then().statusCode(200).body("foo", equalTo("bar2")); async.complete(); } @Test public void testPutMultipleBranchesAfterImmediateExpiration(TestContext context) { Async async = context.async(); given(). header("x-expire-after", "0"). body("{ \"foo\": \"bar1\" }"). when(). put("resexpireimmediatly/branch1"). then(). assertThat().statusCode(200); given(). header("x-expire-after", "0"). body("{ \"foo\": \"bar2\" }"). when(). put("resexpireimmediatly/branch2"). then(). assertThat().statusCode(200); given(). header("x-expire-after", "0"). body("{ \"foo\": \"bar3\" }"). when(). put("resexpireimmediatly/branch3"). then(). assertThat().statusCode(200); await().atMost(TWO_SECONDS).until(() -> get("resexpireimmediatly/branch1").statusCode(), equalTo(404)); when().get("resexpireimmediatly/branch2").then().assertThat().statusCode(404); when().get("resexpireimmediatly/branch3").then().assertThat().statusCode(404); given(). header("x-expire-after", "100"). body("{ \"foo\": \"bar11\" }"). when(). put("resexpireimmediatly/branch1"). then(). assertThat().statusCode(200); given(). body("{ \"foo\": \"bar22\" }"). when(). put("resexpireimmediatly/branch2"). then(). assertThat().statusCode(200); given(). header("x-expire-after", "10"). body("{ \"foo\": \"bar33\" }"). when(). put("resexpireimmediatly/branch3"). then(). assertThat().statusCode(200); when().get("resexpireimmediatly/branch1").then().statusCode(200).body("foo", equalTo("bar11")); when().get("resexpireimmediatly/branch2").then().statusCode(200).body("foo", equalTo("bar22")); when().get("resexpireimmediatly/branch3").then().statusCode(200).body("foo", equalTo("bar33")); async.complete(); } @Test public void testPutWithNoExpiryAfterImmediateExpiration(TestContext context) { Async async = context.async(); given(). header("x-expire-after", "0"). body("{ \"foo\": \"bar1\" }"). when(). put("resexpireimmediatly/branch1"). then(). assertThat().statusCode(200); when().get("resexpireimmediatly/branch1").then().assertThat().statusCode(404); given(). body("{ \"foo\": \"bar11\" }"). when(). put("resexpireimmediatly/branch1"). then(). assertThat().statusCode(200); when().get("resexpireimmediatly/branch1").then().statusCode(200).body("foo", equalTo("bar11")); async.complete(); } @Test public void testCollectionDoesNotExpireBeforeContainedResource(TestContext context) { Async async = context.async(); given(). body("{ \"foo\": \"bar1\" }"). when(). put("root/foo/bar1"). then(). assertThat().statusCode(200); given(). header("x-expire-after", "1"). body("{ \"foo\": \"bar2\" }"). when(). put("root/foo/bar2"). then(). assertThat().statusCode(200); await().atMost(3, TimeUnit.SECONDS).until(() -> get("root/foo/bar2").statusCode(), equalTo(404)); when().get("root/foo/bar1").then().assertThat().statusCode(200); when().get("root/foo/bar2").then().assertThat().statusCode(404); when().get("root/foo").then().assertThat().statusCode(200) .and().body("foo", hasSize(1)) .and().body("foo", hasItem("bar1")); when().get("root").then().assertThat().statusCode(200).and().body("root", hasItem("foo/")); async.complete(); } @Test public void testCollectionDoesExpireAccordingToOlderContainedResource(TestContext context) { Async async = context.async(); given(). header("x-expire-after", "2"). body("{ \"foo\": \"bar1\" }"). when(). put("root/foo/bar1"). then(). assertThat().statusCode(200); given(). header("x-expire-after", "1"). body("{ \"foo\": \"bar2\" }"). when(). put("root/foo/bar2"). then(). assertThat().statusCode(200); when().get("root/foo").then().assertThat().statusCode(200).and().body("foo", hasItem("bar2")); await().atMost(3, TimeUnit.SECONDS).until(() -> get("root/foo/bar2").statusCode(), equalTo(404)); when().get("root/foo/bar1").then().assertThat().statusCode(200); when().get("root/foo/bar2").then().assertThat().statusCode(404); when().get("root/foo/").then().assertThat().statusCode(200) .and().body("foo", hasSize(1)) .and().body("foo", hasItem("bar1")); when().get("root").then().assertThat().statusCode(200).and().body("root", hasItem("foo/")); await().atMost(3, TimeUnit.SECONDS).until(() -> get("root/foo/bar1").statusCode(), equalTo(404)); when().get("root/foo/bar1").then().assertThat().statusCode(404); when().get("root/foo/bar2").then().assertThat().statusCode(404); when().get("root/foo/").then().assertThat().statusCode(404); when().get("root").then().assertThat().statusCode(404); async.complete(); } }