Coverage Report - org.webslinger.util.tests.TestTTLObject
 
Classes in this File Line Coverage Branch Coverage Complexity
TestTTLObject
77%
91/118
100%
2/2
0
TestTTLObject$1
88%
7/8
100%
1/1
0
TestTTLObject$2
100%
2/2
N/A
0
TestTTLObject$3
100%
3/3
N/A
0
TestTTLObject$4
100%
2/2
N/A
0
TestTTLObject$5
100%
2/2
N/A
0
TestTTLObject$DelayedItem
50%
5/10
0%
0/2
0
TestTTLObject$TTLObjectTestTTLObject
89%
16/18
100%
3/3
0
TestTTLObject$Thrower
N/A
N/A
0
 
 1  
 package org.webslinger.util.tests;
 2  
 
 3  
 import java.io.IOException;
 4  
 import java.util.concurrent.Delayed;
 5  
 import java.util.concurrent.DelayQueue;
 6  
 import java.util.concurrent.CountDownLatch;
 7  
 import java.util.concurrent.TimeUnit;
 8  
 import java.util.concurrent.atomic.AtomicBoolean;
 9  
 import java.util.concurrent.atomic.AtomicInteger;
 10  
 import java.util.concurrent.atomic.AtomicReference;
 11  
 
 12  
 import org.webslinger.httpunit.WebslingerTestCase;
 13  
 import org.webslinger.util.TTLObject;
 14  
 
 15  
 public class TestTTLObject extends WebslingerTestCase {
 16  
     static {
 17  1
         TTLObject.setDefaultTTLForClass(TTLObjectTestTTLObject.class, 100);
 18  1
     }
 19  
 
 20  5
     protected final AtomicInteger doneCount = new AtomicInteger();
 21  5
     protected final AtomicReference<Thread> lastLoadThread = new AtomicReference<Thread>();
 22  5
     protected final AtomicBoolean callSetObject = new AtomicBoolean();
 23  5
     protected final AtomicReference<Thrower> throwException = new AtomicReference<Thrower>();
 24  
 
 25  18
     private final class TTLObjectTestTTLObject extends TTLObject<String> {
 26  
         protected boolean getForeground() {
 27  8
             return false;
 28  
         }
 29  
 
 30  
         protected String load(String old, int serial) throws IOException {
 31  8
             lastLoadThread.set(Thread.currentThread());
 32  
             try {
 33  8
                 Thrower thrower = (Thrower) throwException.get();
 34  8
                 if (thrower != null) {
 35  2
                     throwException.compareAndSet(thrower, null);
 36  2
                     thrower.throwException();
 37  
                 }
 38  6
                 long end = System.nanoTime() + sleepTime * 1000000;
 39  128
                 while (System.nanoTime() <= end) {
 40  123
                     Thread.sleep(10);
 41  123
                     if (checkSerial(serial)) break;
 42  
                 }
 43  0
             } catch (InterruptedException e) {
 44  0
                 throw (IOException) new IOException(e.getMessage()).initCause(e);
 45  
             } finally {
 46  8
                 doneCount.incrementAndGet();
 47  6
             }
 48  6
             return loadData;
 49  
         }
 50  
 
 51  
         public void set(String value) throws IOException {
 52  4
             setObject(value);
 53  4
         }
 54  
     }
 55  
 
 56  5
     protected final TTLObjectTestTTLObject object = new TTLObjectTestTTLObject();
 57  
     protected String loadData;
 58  
     protected long sleepTime;
 59  5
     protected final DelayQueue<DelayedItem> setObjectQueue = new DelayQueue<DelayedItem>();
 60  5
     protected volatile boolean quit = false;
 61  
     protected Thread thread;
 62  
 
 63  
     public TestTTLObject(String name) {
 64  5
         super(name);
 65  5
     }
 66  
 
 67  
     protected void setUp() throws InterruptedException {
 68  5
         final CountDownLatch latch = new CountDownLatch(1);
 69  5
         thread = new Thread() {
 70  
             public void run() {
 71  5
                 latch.countDown();
 72  11
                 while (!quit) {
 73  
                     try {
 74  6
                         object.set(setObjectQueue.take().value);
 75  5
                     } catch (InterruptedException e) {
 76  0
                     } catch (IOException e) {
 77  6
                     }
 78  
                 }
 79  5
             }
 80  
         };
 81  5
         thread.setDaemon(true);
 82  5
         thread.start();
 83  5
         latch.await();
 84  5
     }
 85  
 
 86  
     protected void tearDown() throws InterruptedException {
 87  5
         quit = true;
 88  5
         thread.interrupt();
 89  5
         thread.join();
 90  5
         doneCount.set(0);
 91  5
         lastLoadThread.set(null);
 92  5
         callSetObject.set(false);
 93  5
         throwException.set(null);
 94  5
     }
 95  
 
 96  
     protected void assertGetObject(String label, String wantedData, int wantedLoadCount, int wantedDoneCount, long minTime, long maxTime) throws Exception {
 97  15
         long t1 = System.nanoTime();
 98  15
         assertEquals(label + ": data", wantedData, object.getObject());
 99  12
         assertEquals(label + ": doneCount", wantedDoneCount, doneCount.get());
 100  12
         long t2 = System.nanoTime();
 101  12
         long time = t2 - t1;
 102  12
         assertTrue(label + ": long enough(" + time + " >= " + minTime + ")", time >= minTime);
 103  12
         assertTrue(label + ": quick enough(" + time + " <= " + maxTime + ")", time <= maxTime);
 104  12
     }
 105  
 
 106  
     public void testGetTTL() throws Exception {
 107  
         try {
 108  1
             new TTLObject() {
 109  
                 protected Object load(Object old) throws IOException {
 110  1
                     return old;
 111  
                 }
 112  
             }.getObject();
 113  0
             fail("Did not detect a missing default ttl");
 114  1
         } catch (IllegalArgumentException e) {
 115  
             // ignore
 116  0
         }
 117  
         try {
 118  1
             new TTLObject() {
 119  
                 protected long getTTL() {
 120  1
                     return 1000;
 121  
                 }
 122  
 
 123  
                 protected Object load(Object old) throws IOException {
 124  1
                     return old;
 125  
                 }
 126  
             }.getObject();
 127  0
         } catch (IllegalArgumentException e) {
 128  0
             fail("Thought the ttl was missing");
 129  
             // ignore
 130  1
         }
 131  1
     }
 132  
 
 133  
     public void testGet() throws Exception {
 134  1
         loadData = "1";
 135  1
         sleepTime = 1000;
 136  
         // 
 137  1
         assertGetObject("Fetch data first time, blocking", loadData, 1, 1, 950000000, 1200000000);
 138  1
         loadData = "2";
 139  1
         sleepTime = 0;
 140  1
         assertGetObject("Not called all the time", "1", 1, 1, 0, 100000000);
 141  1
         Thread.sleep(300);
 142  1
         assertGetObject("Stale data, starting regen", "1", 1, 1, 0, 100000000);
 143  1
         Thread.sleep(300);
 144  1
         assertGetObject("Refreshed with old data", loadData, 2, 2, 0, 100000000);
 145  1
         loadData = "3";
 146  1
         sleepTime = 1000;
 147  1
         Thread.sleep(200);
 148  1
         assertGetObject("Load called, serve stale data", "2", 3, 2, 0, 100000000);
 149  1
         Thread.sleep(200);
 150  1
         assertGetObject("Load called, serve stale data", "2", 3, 2, 0, 100000000);
 151  1
         Thread.sleep(200);
 152  1
         assertGetObject("Load called, serve stale data", "2", 3, 2, 0, 100000000);
 153  1
         Thread.sleep(800);
 154  1
         assertGetObject("Serve new data", loadData, 3, 3, 0, 100000000);
 155  1
         object.set("a");
 156  1
         assertGetObject("Serve set data(a)", "a", 3, 3, 0, 100000000);
 157  1
         Thread.sleep(500);
 158  1
         object.set("b");
 159  1
         assertGetObject("Serve set data(b)", "b", 3, 3, 0, 100000000);
 160  1
     }
 161  
 
 162  
     public void testSet() throws Exception {
 163  1
         object.set("set");
 164  1
         assertEquals("data after set", "set", object.getObject());
 165  1
         assertEquals("no dones", 0, doneCount.get());
 166  1
         loadData = "1";
 167  1
         Thread.sleep(200);
 168  1
         assertGetObject("SET: stale, start load", "set", 1, 0, 0, 100000000);
 169  0
         Thread.sleep(200);
 170  0
         loadData = "2";
 171  0
         sleepTime = 500;
 172  0
         assertGetObject("SET: valid, process load, schedule pulse 1", "1", 1, 1, 0, 100000000);
 173  0
         Thread.sleep(100);
 174  0
         assertGetObject("SET: stale 1", "1", 1, 1, 0, 100000000);
 175  0
         Thread.sleep(100);
 176  0
         assertGetObject("SET: stale 2", "1", 1, 1, 0, 100000000);
 177  0
         Thread.sleep(100);
 178  0
         assertGetObject("SET: stale 3", "1", 1, 1, 0, 100000000);
 179  0
         Thread.sleep(600);
 180  0
         assertGetObject("SET: valid, process load, schedule pulse 2", "2", 2, 2, 0, 100000000);
 181  0
     }
 182  
 
 183  
     public void testSetGetAbort() throws Exception {
 184  1
         loadData = "1";
 185  1
         sleepTime = 1000;
 186  
         // 
 187  1
         setObjectQueue.offer(new DelayedItem(300, "override"));
 188  1
         assertGetObject("Fetch data first time, blocking/setting", "override", 1, 1, 250000000, 400000000);
 189  1
     }
 190  
 
 191  
     public void testThrowException() throws Exception {
 192  1
         loadData = "1";
 193  1
         sleepTime = 100;
 194  1
         throwException.set(new Thrower() {
 195  
             public void throwException() throws IOException {
 196  1
                 throw new IOException("exc1");
 197  
             }
 198  
         });
 199  
         try {
 200  1
             assertGetObject("Fetch data first time, throw exception", "override", 1, 1, 0, 200000000);
 201  0
             fail("No exception thrown");
 202  1
         } catch (IOException e) {
 203  1
             assertEquals("correct exception thrown", "exc1", e.getMessage());
 204  0
         }
 205  1
         loadData = "2";
 206  1
         sleepTime = 100;
 207  1
         assertGetObject("Fetch data after exception, blocked", loadData, 2, 2, 50000000, 200000000);
 208  1
         loadData = "3";
 209  1
         sleepTime = 500;
 210  1
         throwException.set(new Thrower() {
 211  
             public void throwException() throws IOException {
 212  1
                 throw new IOException("exc2");
 213  
             }
 214  
         });
 215  1
         Thread.sleep(200);
 216  
         try {
 217  1
             assertGetObject("Fetch data second time, stale, process pulse", "2", 3, 2, 0, 200000000);
 218  1
         } catch (IOException e) {
 219  1
             fail("Exception thrown");
 220  0
         }
 221  0
         Thread.sleep(400);
 222  
         try {
 223  0
             assertGetObject("Fetch data second time, throw exception", "2", 3, 2, 0, 200000000);
 224  0
             fail("No exception thrown");
 225  0
         } catch (IOException e) {
 226  0
             assertEquals("correct exception thrown", "exc2", e.getMessage());
 227  0
         }
 228  0
     }
 229  
 
 230  0
     private static final class DelayedItem implements Delayed {
 231  
         protected final long when;
 232  
         protected final String value;
 233  
 
 234  1
         protected DelayedItem(long milliseconds, String value) {
 235  1
             when = System.nanoTime() + TimeUnit.NANOSECONDS.convert(milliseconds, TimeUnit.MILLISECONDS);
 236  1
             this.value = value;
 237  1
         }
 238  
 
 239  
         public long getDelay(TimeUnit unit) {
 240  2
             return unit.convert(when - System.nanoTime(), TimeUnit.NANOSECONDS);
 241  
         }
 242  
 
 243  
         public int compareTo(Delayed other) {
 244  0
             return compareTo((DelayedItem) other);
 245  
         }
 246  
 
 247  
         public int compareTo(DelayedItem other) {
 248  0
             if (when < other.when) return -1;
 249  0
             if (when > other.when) return 1;
 250  0
             return value.compareTo(other.value);
 251  
         }
 252  
     }
 253  
 
 254  
     public interface Thrower {
 255  
         void throwException() throws InterruptedException, IOException;
 256  
     }
 257  
 }