package com.sogeti.droidnetworking.test.integration; import com.google.mockwebserver.MockResponse; import com.google.mockwebserver.MockWebServer; import com.google.mockwebserver.RecordedRequest; import com.sogeti.droidnetworking.NetworkEngine; import com.sogeti.droidnetworking.NetworkOperation; import org.junit.After; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Map; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; @RunWith(RobolectricTestRunner.class) public abstract class CacheTests { protected MockWebServer server; @After public void tearDown() throws Throwable { server.shutdown(); } @Test public void cacheHeaders() throws Throwable { MockResponse response = new MockResponse(); response.setBody(""); response.setResponseCode(200); response.addHeader("Cache-Control", "max-age=0"); response.addHeader("Etag", "\"831363a99b0f91672533a537c2304208\""); server.enqueue(response); server.play(8080); NetworkEngine.getInstance().clearCache(); NetworkOperation operation = NetworkEngine.getInstance().createOperationWithURLString("http://localhost"); NetworkEngine.getInstance().executeOperation(operation); assertTrue(operation.getHttpStatusCode() == 200); Map<String, String> cacheHeaders = operation.getCacheHeaders(); assertFalse(cacheHeaders.get("Expires") == null); try { SimpleDateFormat simpleDateFormat = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z"); Date expires = simpleDateFormat.parse(cacheHeaders.get("Expires")); assertTrue(expires.before(new Date())); } catch (ParseException e) { assertTrue(false); } // ETag is a MD5 sum of the content. If the content changes this ETag will not be valid. assertFalse(cacheHeaders.get("ETag") == null); assertTrue(cacheHeaders.get("ETag").equalsIgnoreCase("\"831363a99b0f91672533a537c2304208\"")); assertTrue(cacheHeaders.get("Last-Modified") == null); } @Test public void notModified() throws Throwable { MockResponse response = new MockResponse(); response.setBody(""); response.setResponseCode(200); response.addHeader("Cache-Control", "max-age=0"); response.addHeader("Etag", "\"831363a99b0f91672533a537c2304208\""); server.enqueue(response); response.setBody(""); response.setResponseCode(304); response.addHeader("Cache-Control", "max-age=0"); response.addHeader("Etag", "\"831363a99b0f91672533a537c2304208\""); server.enqueue(response); server.play(8080); NetworkEngine.getInstance().clearCache(); NetworkOperation operation = NetworkEngine.getInstance().createOperationWithURLString("http://localhost"); NetworkEngine.getInstance().executeOperation(operation); assertTrue(operation.getHttpStatusCode() == 200); // Save the cache headers from the first request Map<String, String> cacheHeaders = operation.getCacheHeaders(); NetworkEngine.getInstance().clearCache(); // Create a new request operation = NetworkEngine.getInstance().createOperationWithURLString("http://localhost"); // Update the headers with the saved cache headers (ETag) operation.updateOperation(cacheHeaders); // Execute the operation NetworkEngine.getInstance().executeOperation(operation); // The server should respond with 304 Not Modified since we supplied a ETag assertTrue(operation.getHttpStatusCode() == 304); // Verify that an Etag was not sent to server in the first request RecordedRequest request = server.takeRequest(); assertTrue(request.getHeader("If-None-Match") == null); // Verify that an Etag was sent to server in the second request request = server.takeRequest(); assertTrue(request.getHeader("If-None-Match").equals("\"831363a99b0f91672533a537c2304208\"")); } @Test public void cacheTC1() throws Throwable { MockResponse response = new MockResponse(); response.setBody("OK"); response.setResponseCode(200); response.addHeader("Cache-Control", "max-age=10"); response.addHeader("Etag", "\"831363a99b0f91672533a537c2304208\""); server.enqueue(response); server.play(8080); NetworkEngine.getInstance().clearCache(); NetworkOperation operation = NetworkEngine.getInstance().createOperationWithURLString("http://localhost"); NetworkEngine.getInstance().executeOperation(operation); assertTrue(operation.getHttpStatusCode() == 200); assertTrue(operation.isCachedResponse() == false); assertTrue(operation.getResponseString().equalsIgnoreCase("OK")); byte[] responseData = operation.getResponseData(); // There should be some response data assertFalse(responseData == null); // Create an new operation operation = NetworkEngine.getInstance().createOperationWithURLString("http://localhost"); NetworkEngine.getInstance().executeOperation(operation); assertTrue(operation.getStatus() == NetworkOperation.STATUS_COMPLETED); // Check that we get a 200 response, that is cached with the same data as before assertTrue(operation.getHttpStatusCode() == 200); assertTrue(operation.isCachedResponse() == true); assertTrue(operation.getResponseString().equalsIgnoreCase("OK")); } @Test public void cacheTC2() throws Throwable { MockResponse response = new MockResponse(); response.setBody("OK"); response.setResponseCode(200); response.addHeader("Cache-Control", "max-age=1"); response.addHeader("Etag", "\"831363a99b0f91672533a537c2304208\""); server.enqueue(response); response.setBody("OK"); response.setResponseCode(200); response.addHeader("Cache-Control", "max-age=1"); response.addHeader("Etag", "\"831363a99b0f91672533a537c2304208\""); server.enqueue(response); server.play(8080); NetworkEngine.getInstance().clearCache(); NetworkOperation operation = NetworkEngine.getInstance().createOperationWithURLString("http://localhost"); NetworkEngine.getInstance().executeOperation(operation); assertTrue(operation.getHttpStatusCode() == 200); assertTrue(operation.isCachedResponse() == false); operation = NetworkEngine.getInstance().createOperationWithURLString("http://localhost"); NetworkEngine.getInstance().executeOperation(operation); // Check that we get a 200 response, that is cached with the same data as before assertTrue(operation.getHttpStatusCode() == 200); assertTrue(operation.isCachedResponse() == true); try { Thread.sleep(1500L); // after 2 seconds the cache is no longer valid } catch (Exception e) { } // Create an new operation operation = NetworkEngine.getInstance().createOperationWithURLString("http://localhost"); NetworkEngine.getInstance().executeOperation(operation); // Check that we get a 200 response, that is not cached assertTrue(operation.getHttpStatusCode() == 200); assertTrue(operation.isCachedResponse() == false); } @Test public void cacheTC3() throws Throwable { MockResponse response = new MockResponse(); response.setBody("OK"); response.setResponseCode(200); response.addHeader("Cache-Control", "max-age=1"); response.addHeader("Etag", "\"831363a99b0f91672533a537c2304208\""); server.enqueue(response); response.setBody("OK"); response.setResponseCode(304); response.addHeader("Cache-Control", "max-age=1"); response.addHeader("Etag", "\"831363a99b0f91672533a537c2304208\""); server.enqueue(response); server.play(8080); NetworkEngine.getInstance().clearCache(); NetworkOperation operation = NetworkEngine.getInstance().createOperationWithURLString("http://localhost"); NetworkEngine.getInstance().executeOperation(operation); assertTrue(operation.getHttpStatusCode() == 200); assertTrue(operation.isCachedResponse() == false); operation = NetworkEngine.getInstance().createOperationWithURLString("http://localhost"); NetworkEngine.getInstance().executeOperation(operation); // Check that we get a 200 response, that is cached with the same data as before assertTrue(operation.getHttpStatusCode() == 200); assertTrue(operation.isCachedResponse() == true); try { Thread.sleep(1500L); // after 2 seconds the cache is no longer valid } catch (Exception e) { } // Create an new operation operation = NetworkEngine.getInstance().createOperationWithURLString("http://localhost"); NetworkEngine.getInstance().executeOperation(operation); // Check that we get a 200 response, that is cached since Etag hasen't changed assertTrue(operation.getHttpStatusCode() == 200); assertTrue(operation.isCachedResponse() == true); } @Test public void uniqueIdentifier() { NetworkEngine.getInstance().clearCache(); NetworkOperation operation = NetworkEngine.getInstance() .createOperationWithURLString("http://localhost"); assertFalse(operation == null); assertTrue(operation.getUniqueIdentifier().equalsIgnoreCase("c6c9381420cb8621b071d157b1876901")); } }