From 5d67e165d9a492f2cc18a5cda734336dd6a4606c Mon Sep 17 00:00:00 2001 From: reger Date: Tue, 9 Dec 2014 00:58:08 +0100 Subject: [PATCH] remove redundant null check in ResponseHeader.lastModified added a JUnit testcase for ResponseHeader dates (using age()), adjusted age() to pass all tests --- .../yacy/cora/protocol/ResponseHeader.java | 27 +++- .../cora/protocol/ResponseHeaderTest.java | 135 ++++++++++++++++++ 2 files changed, 156 insertions(+), 6 deletions(-) create mode 100644 test/net/yacy/cora/protocol/ResponseHeaderTest.java diff --git a/source/net/yacy/cora/protocol/ResponseHeader.java b/source/net/yacy/cora/protocol/ResponseHeader.java index 7c1b3924c..05e651811 100644 --- a/source/net/yacy/cora/protocol/ResponseHeader.java +++ b/source/net/yacy/cora/protocol/ResponseHeader.java @@ -32,10 +32,11 @@ public class ResponseHeader extends HeaderFramework { private static final long serialVersionUID = 0L; + // cached values for quicker repeated access private Date date_cache_Date = null; private Date date_cache_Expires = null; private Date date_cache_LastModified = null; - + public ResponseHeader(final int statusCode) { super(); this.put(HeaderFramework.STATUS_CODE, Integer.toString(statusCode)); @@ -67,7 +68,11 @@ public class ResponseHeader extends HeaderFramework { return 200; } } - + + /** + * Get the http field Date or now (if header date missing) + * @return date message was created or now + */ public Date date() { if (this.date_cache_Date != null) return this.date_cache_Date; final Date d = headerDate(HeaderFramework.DATE); @@ -76,26 +81,36 @@ public class ResponseHeader extends HeaderFramework { return this.date_cache_Date; } + /** + * get http field Expires if available + * @return date or null + */ public Date expires() { if (this.date_cache_Expires != null) return this.date_cache_Expires; this.date_cache_Expires = headerDate(HeaderFramework.EXPIRES); return this.date_cache_Expires; } + /** + * get http field Last-Modified or now (if header field is missing) + * @return valid date (always != null) + */ public Date lastModified() { if (this.date_cache_LastModified != null) return this.date_cache_LastModified; Date d = headerDate(HeaderFramework.LAST_MODIFIED); - if (d == null) d = date(); final Date now = new Date(); this.date_cache_LastModified = (d == null) ? date() : d.after(now) ? now : d; return this.date_cache_LastModified; } + /** + * age in milliseconds (difference between now and last_modified) + * @return age in milliseconds + */ public long age() { final Date lm = lastModified(); - final Date sd = date(); - if (lm == null) return Long.MAX_VALUE; - return ((sd == null) ? new Date() : sd).getTime() - lm.getTime(); + final Date now = new Date(); + return now.getTime() - lm.getTime(); } public boolean gzip() { diff --git a/test/net/yacy/cora/protocol/ResponseHeaderTest.java b/test/net/yacy/cora/protocol/ResponseHeaderTest.java new file mode 100644 index 000000000..4d16f381d --- /dev/null +++ b/test/net/yacy/cora/protocol/ResponseHeaderTest.java @@ -0,0 +1,135 @@ +package net.yacy.cora.protocol; + +import java.util.Date; +import org.junit.Test; +import static org.junit.Assert.*; + +public class ResponseHeaderTest { + + /** + * Test of age method, of class ResponseHeader. + * testing many combination of header.date and header.last_modified + * test goal: age is suppose to always >= 0 + */ + @Test + public void testAge() { + // because ResponseHeader caches date values internally on 1st access, + // we need to create a new instance for every testcase + + ResponseHeader testhdr1 = new ResponseHeader(200); + ResponseHeader testhdr2 = new ResponseHeader(200); + ResponseHeader testhdr3 = new ResponseHeader(200); + + // access-sequence 1 = age() without accessing any date before + // access-sequence 2 = access date() then age() + // access-sequence 3 = access lastModified() then age() + + // test case with sorce: date=null lastmodified=null + long age1 = testhdr1.age(); + + testhdr2.date(); + testhdr3.lastModified(); + + assertEquals("access-sequence 1 date=null lastmod=null AGE="+age1, 0, age1); + + testhdr2.lastModified(); + + long age2 = testhdr2.age(); + assertEquals("access-sequence 2 date=null lastmod=null AGE="+age2, 0, age2); + + testhdr3.date(); + + long age3 = testhdr3.age(); + assertEquals("access-sequence 3 date=null lastmod=null AGE="+age3, 0, age3); + + Date past = new Date(System.currentTimeMillis() / 2); + Date future = new Date(System.currentTimeMillis() * 2); + + Date[] testdate = new Date[3]; + testdate[0] = past; + testdate[1] = new Date(); + testdate[2] = future; + String[] testdatename = new String[] {"past","now","future"}; // date names just for output + + for (int id = 0; id < testdate.length; id++) { + + // test case with sorce: date=testdate(x) lastmodified=null + testhdr1 = new ResponseHeader(200); + testhdr1.put(HeaderFramework.DATE, HeaderFramework.formatRFC1123(testdate[id])); + testhdr2 = new ResponseHeader(200); + testhdr2.put(HeaderFramework.DATE, HeaderFramework.formatRFC1123(testdate[id])); + testhdr3 = new ResponseHeader(200); + testhdr3.put(HeaderFramework.DATE, HeaderFramework.formatRFC1123(testdate[id])); + + age1 = testhdr1.age(); + testhdr2.date(); + testhdr3.lastModified(); + + assertTrue("access-sequence 1."+id+" date=" + testdatename[id] + " lastmod=null AGE= " + age1, age1 >= 0); + + age2 = testhdr2.age(); + assertTrue("access-sequence 2."+id+" date=" + testdatename[id] + " lastmod=null AGE= " + age2, age2 >= 0); + + age3 = testhdr3.age(); + assertTrue("access-sequence 3."+id+" date=" + testdatename[id] + " lastmod=null AGE= " + age3, age3 >= 0); + + // test case with sorce: date=null lastmodified=testdat(x) + testhdr1 = new ResponseHeader(200); + testhdr1.put(HeaderFramework.LAST_MODIFIED, HeaderFramework.formatRFC1123(testdate[id])); + testhdr2 = new ResponseHeader(200); + testhdr2.put(HeaderFramework.LAST_MODIFIED, HeaderFramework.formatRFC1123(testdate[id])); + testhdr3 = new ResponseHeader(200); + testhdr3.put(HeaderFramework.LAST_MODIFIED, HeaderFramework.formatRFC1123(testdate[id])); + + age1 = testhdr1.age(); + testhdr2.date(); + testhdr3.lastModified(); + + assertTrue("access-sequence 1."+id+" date=null lastmod=" + testdatename[id] + " AGE= " + age1, age1 >= 0); + + age2 = testhdr2.age(); + assertTrue("access-sequence 2."+id+" date=null lastmod=" + testdatename[id] + " AGE= " + age2, age2 >= 0); + + age3 = testhdr3.age(); + assertTrue("access-sequence 3."+id+" date=null lastmod=" + testdatename[id] + " AGE= " + age3, age3 >= 0); + + for (int imd = 0; imd < testdate.length; imd++) { + // test case with sorce: date=testdate(x) lastmodified=testdate(y) + testhdr1 = new ResponseHeader(200); + testhdr1.put(HeaderFramework.DATE, HeaderFramework.formatRFC1123(testdate[id])); + testhdr1.put(HeaderFramework.LAST_MODIFIED, HeaderFramework.formatRFC1123(testdate[imd])); + + testhdr2 = new ResponseHeader(200); + testhdr2.put(HeaderFramework.DATE, HeaderFramework.formatRFC1123(testdate[id])); + testhdr2.put(HeaderFramework.LAST_MODIFIED, HeaderFramework.formatRFC1123(testdate[imd])); + + testhdr3 = new ResponseHeader(200); + testhdr3.put(HeaderFramework.DATE, HeaderFramework.formatRFC1123(testdate[id])); + testhdr3.put(HeaderFramework.LAST_MODIFIED, HeaderFramework.formatRFC1123(testdate[imd])); + + age1 = testhdr1.age(); + + testhdr2.date(); + testhdr3.lastModified(); + + assertTrue("case 1."+id+"."+imd+" date=" + testdatename[id] + " lastmod=" + testdatename[imd] + " AGE= " + age1, age1 >= 0); + + // hint to mismatch of date + Date d1 = testhdr1.date(); + Date m1 = testhdr1.lastModified(); + if (d1.before(m1)) { + System.err.println("this faulty combination with lastmod after date (date="+testdatename[id]+" lastmod="+testdatename[imd]+") is accepted without correction"); + } + + age2 = testhdr2.age(); + assertTrue("case 2."+id+"."+imd+" date=" + testdatename[id] + " lastmod=" + testdatename[imd] + " AGE= " + age2, age2 >= 0); + + age3 = testhdr3.age(); + assertTrue("case 3."+id+"."+imd+" date=" + testdatename[id] + " lastmod=" + testdatename[imd] + " AGE= " + age3, age3 >= 0); + } + + } + + } + +}