summaryrefslogtreecommitdiffstats
path: root/simple/simple-common/src/test/java/org/simpleframework
diff options
context:
space:
mode:
authormikaelpeltier <mikaelpeltier@google.com>2015-06-24 14:31:11 +0200
committerMikael Peltier <mikaelpeltier@google.com>2015-06-24 14:59:36 +0000
commit04563874ddaac702d6c715eaa89c29b253f4c54e (patch)
treec305fa98670c3e80be494cc054a8e31b51bfe7f2 /simple/simple-common/src/test/java/org/simpleframework
parentf1828481ebcfee3bddc323fca178a4502a60ceef (diff)
downloadtoolchain_jack-04563874ddaac702d6c715eaa89c29b253f4c54e.zip
toolchain_jack-04563874ddaac702d6c715eaa89c29b253f4c54e.tar.gz
toolchain_jack-04563874ddaac702d6c715eaa89c29b253f4c54e.tar.bz2
Add simpleframework source files
Change-Id: I18d01df16de2868ca5458f79a88e6070b75db2c3 (cherry picked from commit 3e9f84cf7b22f6970eb8041ca38d12d75c6bb270)
Diffstat (limited to 'simple/simple-common/src/test/java/org/simpleframework')
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/KeyTest.java195
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/buffer/ArrayBufferTest.java54
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/buffer/BufferAllocatorTest.java79
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/buffer/FileBufferTest.java45
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/buffer/FileByteQueue.java109
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/buffer/FileByteQueueTest.java22
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ArrayByteQueue.java100
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ArrayByteQueueTest.java119
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/BufferQueue.java67
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/BufferQueueTest.java44
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ByteQueue.java13
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ByteQueueStream.java40
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/lease/ContractQueueTest.java57
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/lease/ContractTest.java40
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/lease/LeaseManagerTest.java227
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/lease/LeaseTest.java87
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/lease/TimeTestCase.java25
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/thread/SchedulerTest.java65
-rw-r--r--simple/simple-common/src/test/java/org/simpleframework/common/thread/TransientApplication.java54
19 files changed, 1442 insertions, 0 deletions
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/KeyTest.java b/simple/simple-common/src/test/java/org/simpleframework/common/KeyTest.java
new file mode 100644
index 0000000..f9056fe
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/KeyTest.java
@@ -0,0 +1,195 @@
+package org.simpleframework.common;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.TestCase;
+
+/**
+ * Test for fast case insensitive mapping for headers that have been taken
+ * from the request HTTP header or added to the response HTTP header.
+ *
+ * @author Niall Gallagher
+ */
+public class KeyTest extends TestCase {
+
+ public class Index implements Name {
+
+ private final String value;
+
+ public Index(String value) {
+ this.value = value.toLowerCase();
+ }
+
+ public int hashCode() {
+ return value.hashCode();
+ }
+
+ public boolean equals(Object key) {
+ if(key instanceof Name) {
+ return key.equals(value);
+ }
+ if(key instanceof String) {
+ return key.equals(value);
+ }
+ return false;
+ }
+ }
+
+ public interface Name {
+
+ public int hashCode();
+ public boolean equals(Object value);
+ }
+
+ public class ArrayName implements Name {
+
+ private String cache;
+ private byte[] array;
+ private int off;
+ private int size;
+ private int hash;
+
+ public ArrayName(byte[] array) {
+ this(array, 0, array.length);
+ }
+
+ public ArrayName(byte[] array, int off, int size) {
+ this.array = array;
+ this.size = size;
+ this.off = off;
+ }
+
+ public boolean equals(Object value) {
+ if(value instanceof String) {
+ String text = value.toString();
+
+ return equals(text);
+ }
+ return false;
+ }
+
+ public boolean equals(String value) {
+ int length = value.length();
+
+ if(length != size) {
+ return false;
+ }
+ for(int i = 0; i < size; i++) {
+ int left = value.charAt(i);
+ int right = array[off + i];
+
+ if(right >= 'A' && right <= 'Z') {
+ right = (right - 'A') + 'a';
+ }
+ if(left != right) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public int hashCode() {
+ int code = hash;
+
+ if(code == 0) {
+ int pos = off;
+
+ for(int i = 0; i < size; i++) {
+ int next = array[pos++];
+
+ if(next >= 'A' && next <= 'Z') {
+ next = (next - 'A') + 'a';
+ }
+ code = 31*code + next;
+ }
+ hash = code;
+ }
+ return code;
+ }
+ }
+
+ public class StringName implements Name {
+
+ private final String value;
+ private final String key;
+
+ public StringName(String value) {
+ this.key = value.toLowerCase();
+ this.value = value;
+ }
+
+ public int hashCode() {
+ return key.hashCode();
+ }
+
+ public boolean equals(Object value) {
+ return value.equals(key);
+ }
+ }
+
+ public class NameTable<T> {
+
+ private final Map<Name, T> map;
+
+ public NameTable() {
+ this.map = new HashMap<Name, T>();
+ }
+
+ public void put(Name key, T value) {
+ map.put(key, value);
+ }
+
+ public void put(String text, T value) {
+ Name key = new StringName(text);
+
+ map.put(key, value);
+ }
+
+ public T get(String key) {
+ Index index = new Index(key);
+
+ return map.get(index);
+ }
+
+ public T remove(String key) {
+ Index index = new Index(key);
+
+ return map.remove(index);
+ }
+ }
+
+ public void testName() {
+ Name contentLength = new ArrayName("Content-Length".getBytes());
+ Name contentType = new ArrayName("Content-Type".getBytes());
+ Name transferEncoding = new ArrayName("Transfer-Encoding".getBytes());
+ Name userAgent = new ArrayName("User-Agent".getBytes());
+ NameTable<String> map = new NameTable<String>();
+
+ assertEquals(contentLength.hashCode(), "Content-Length".toLowerCase().hashCode());
+ assertEquals(contentType.hashCode(), "Content-Type".toLowerCase().hashCode());
+ assertEquals(transferEncoding.hashCode(), "Transfer-Encoding".toLowerCase().hashCode());
+ assertEquals(userAgent.hashCode(), "User-Agent".toLowerCase().hashCode());
+
+ map.put(contentLength, "1024");
+ map.put(contentType, "text/html");
+ map.put(transferEncoding, "chunked");
+ map.put(userAgent, "Mozilla/4.0");
+ map.put("Date", "18/11/1977");
+ map.put("Accept", "text/plain, text/html, image/gif");
+
+ assertEquals(map.get("Content-Length"), "1024");
+ assertEquals(map.get("CONTENT-LENGTH"), "1024");
+ assertEquals(map.get("content-length"), "1024");
+ assertEquals(map.get("Content-length"), "1024");
+ assertEquals(map.get("Content-Type"), "text/html");
+ assertEquals(map.get("Transfer-Encoding"), "chunked");
+ assertEquals(map.get("USER-AGENT"), "Mozilla/4.0");
+ assertEquals(map.get("Accept"), "text/plain, text/html, image/gif");
+ assertEquals(map.get("ACCEPT"), "text/plain, text/html, image/gif");
+ assertEquals(map.get("accept"), "text/plain, text/html, image/gif");
+ assertEquals(map.get("DATE"), "18/11/1977");
+ assertEquals(map.get("Date"), "18/11/1977");
+ assertEquals(map.get("date"), "18/11/1977");
+ }
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/buffer/ArrayBufferTest.java b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/ArrayBufferTest.java
new file mode 100644
index 0000000..1f6f494
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/ArrayBufferTest.java
@@ -0,0 +1,54 @@
+package org.simpleframework.common.buffer;
+
+import org.simpleframework.common.buffer.ArrayBuffer;
+import org.simpleframework.common.buffer.Buffer;
+
+import junit.framework.TestCase;
+
+public class ArrayBufferTest extends TestCase {
+
+ public void testBuffer() throws Exception {
+ Buffer buffer = new ArrayBuffer(1, 2);
+
+ buffer.append(new byte[]{'a'}).append(new byte[]{'b'});
+
+ assertEquals(buffer.encode(), "ab");
+ assertEquals(buffer.encode("ISO-8859-1"), "ab");
+
+ boolean overflow = false;
+
+ try {
+ buffer.append(new byte[]{'c'});
+ } catch(Exception e) {
+ overflow = true;
+ }
+ assertTrue(overflow);
+
+ buffer.clear();
+
+ assertEquals(buffer.encode(), "");
+ assertEquals(buffer.encode("UTF-8"), "");
+
+ buffer = new ArrayBuffer(1024, 2048);
+ buffer.append("abcdefghijklmnopqrstuvwxyz".getBytes());
+
+ Buffer alphabet = buffer.allocate();
+ alphabet.append("ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes());
+
+ Buffer digits = buffer.allocate();
+ digits.append("0123456789".getBytes());
+
+ assertEquals(alphabet.encode(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ assertEquals(digits.encode(), "0123456789");
+ assertEquals(buffer.encode(), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
+
+ Buffer extra = digits.allocate();
+ extra.append("#@?".getBytes());
+
+ assertEquals(extra.encode(), "#@?");
+ assertEquals(digits.encode(), "0123456789#@?");
+ assertEquals(buffer.encode(), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#@?");
+ assertEquals(buffer.length(), 65);
+ }
+
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/buffer/BufferAllocatorTest.java b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/BufferAllocatorTest.java
new file mode 100644
index 0000000..9584047
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/BufferAllocatorTest.java
@@ -0,0 +1,79 @@
+package org.simpleframework.common.buffer;
+
+import org.simpleframework.common.buffer.Allocator;
+import org.simpleframework.common.buffer.ArrayAllocator;
+import org.simpleframework.common.buffer.Buffer;
+import org.simpleframework.common.buffer.BufferAllocator;
+
+import junit.framework.TestCase;
+
+public class BufferAllocatorTest extends TestCase {
+
+ public void testBuffer() throws Exception {
+ Allocator allocator = new ArrayAllocator(1, 2);
+ Buffer buffer = new BufferAllocator(allocator, 1, 2);
+
+ buffer.append(new byte[]{'a'}).append(new byte[]{'b'});
+
+ assertEquals(buffer.encode(), "ab");
+ assertEquals(buffer.encode("ISO-8859-1"), "ab");
+
+ boolean overflow = false;
+
+ try {
+ buffer.append(new byte[]{'c'});
+ } catch(Exception e) {
+ overflow = true;
+ }
+ assertTrue(overflow);
+
+ buffer.clear();
+
+ assertEquals(buffer.encode(), "");
+ assertEquals(buffer.encode("UTF-8"), "");
+
+ allocator = new ArrayAllocator(1024, 2048);
+ buffer = new BufferAllocator(allocator, 1024, 2048);
+ buffer.append("abcdefghijklmnopqrstuvwxyz".getBytes());
+
+ Buffer alphabet = buffer.allocate();
+ alphabet.append("ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes());
+
+ Buffer digits = buffer.allocate();
+ digits.append("0123456789".getBytes());
+
+ assertEquals(alphabet.encode(), "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ assertEquals(digits.encode(), "0123456789");
+ assertEquals(buffer.encode(), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
+
+ Buffer extra = digits.allocate();
+ extra.append("#@?".getBytes());
+
+ assertEquals(extra.encode(), "#@?");
+ assertEquals(extra.length(), 3);
+ assertEquals(digits.encode(), "0123456789#@?");
+ assertEquals(digits.length(), 13);
+ assertEquals(buffer.encode(), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#@?");
+ assertEquals(buffer.length(), 65);
+ }
+
+ public void testCascadingBufferAllocator() throws Exception {
+ Allocator allocator = new ArrayAllocator(1024, 2048);
+ allocator = new BufferAllocator(allocator, 1024, 2048);
+ allocator = new BufferAllocator(allocator, 1024, 2048);
+ allocator = new BufferAllocator(allocator, 1024, 2048);
+ allocator = new BufferAllocator(allocator, 1024, 2048);
+
+ Buffer buffer = allocator.allocate(1024);
+
+ buffer.append("abcdefghijklmnopqrstuvwxyz".getBytes());
+
+ assertEquals(buffer.encode(), "abcdefghijklmnopqrstuvwxyz");
+
+ buffer.append("ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes());
+
+ assertEquals(buffer.encode(), "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ assertEquals(buffer.length(), 52);
+ }
+
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/buffer/FileBufferTest.java b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/FileBufferTest.java
new file mode 100644
index 0000000..54cb142
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/FileBufferTest.java
@@ -0,0 +1,45 @@
+package org.simpleframework.common.buffer;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.simpleframework.common.buffer.Buffer;
+import org.simpleframework.common.buffer.FileBuffer;
+
+import junit.framework.TestCase;
+
+public class FileBufferTest extends TestCase {
+
+ public void testFileBuffer() throws Exception {
+ File tempFile = File.createTempFile(FileBufferTest.class.getSimpleName(), null);
+ Buffer buffer = new FileBuffer(tempFile);
+ buffer.append("abcdefghijklmnopqrstuvwxyz".getBytes());
+
+ Buffer alphabet = buffer.allocate();
+ alphabet.append("ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes());
+
+ Buffer digits = buffer.allocate();
+ digits.append("0123456789".getBytes());
+
+ expect(buffer, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".getBytes());
+ expect(alphabet, "ABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes());
+ expect(digits, "0123456789".getBytes());
+ }
+
+ private void expect(Buffer buffer, byte[] expect) throws IOException {
+ InputStream result = buffer.open();
+
+ for(int i =0; i < expect.length; i++) {
+ byte octet = expect[i];
+ int value = result.read();
+
+ if(value < 0) {
+ throw new IOException("Buffer exhausted too early");
+ }
+ assertEquals(octet, (byte)value);
+ }
+ assertEquals(-1, result.read());
+ }
+
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/buffer/FileByteQueue.java b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/FileByteQueue.java
new file mode 100644
index 0000000..b404562
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/FileByteQueue.java
@@ -0,0 +1,109 @@
+package org.simpleframework.common.buffer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.simpleframework.common.buffer.Allocator;
+import org.simpleframework.common.buffer.Buffer;
+import org.simpleframework.common.buffer.BufferAllocator;
+
+public class FileByteQueue {
+
+ private BlockingQueue<Block> blocks;
+ private BlockAllocator allocator;
+ private Block source;
+
+ public FileByteQueue(Allocator allocator) throws IOException {
+ this.blocks = new LinkedBlockingQueue<Block>();
+ this.allocator = new BlockAllocator(allocator);
+ }
+
+ public int read(byte[] array, int off, int size) throws Exception {
+ int left = blocks.size();
+ int mark = size;
+
+ for(int i = 0; source != null || i < left; i++) {
+ if(source == null) {
+ source = blocks.take();
+ }
+ int remain = source.remaining();
+ int read = Math.min(remain, size);
+
+ if(read > 0) {
+ source.read(array, off, size);
+ size -= read;
+ off += read;
+ }
+ if(remain == 0) {
+ source.close(); // clear up file handles
+ source = null;
+ }
+ if(size <= 0) {
+ return mark;
+ }
+ }
+ return mark - size;
+ }
+
+ public void write(byte[] array, int off, int size) throws Exception {
+ Block buffer = allocator.allocate(array, off, size);
+
+ if(size > 0) {
+ blocks.offer(buffer);
+ }
+ }
+
+ private class BlockAllocator {
+
+ private Allocator allocator;
+
+ public BlockAllocator(Allocator allocator) {
+ this.allocator = new BufferAllocator(allocator);
+ }
+
+ public Block allocate(byte[] array, int off, int size) throws IOException {
+ Buffer buffer = allocator.allocate();
+
+ if(size > 0) {
+ buffer.append(array, off, size);
+ }
+ return new Block(buffer, size);
+ }
+ }
+
+ private class Block {
+
+ private InputStream source;
+ private int remaining;
+ private int size;
+
+ public Block(Buffer buffer, int size) throws IOException {
+ this.source = buffer.open();
+ this.remaining = size;
+ this.size = size;
+ }
+
+ public int read(byte[] array, int off, int size) throws IOException {
+ int count = source.read(array, off, size);
+
+ if(count > 0) {
+ remaining -= size;
+ }
+ return count;
+ }
+
+ public void close() throws IOException {
+ source.close();
+ }
+
+ public int remaining() {
+ return remaining;
+ }
+
+ public int size() {
+ return size;
+ }
+ }
+} \ No newline at end of file
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/buffer/FileByteQueueTest.java b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/FileByteQueueTest.java
new file mode 100644
index 0000000..9699454
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/FileByteQueueTest.java
@@ -0,0 +1,22 @@
+package org.simpleframework.common.buffer;
+
+import junit.framework.TestCase;
+
+public class FileByteQueueTest extends TestCase {
+
+ public void testQueue() throws Exception {
+ /* Allocator allocator = new FileAllocator();
+ FileByteQueue queue = new FileByteQueue(allocator);
+ for(int i = 0; i < 26; i++) {
+ queue.write(new byte[]{(byte)(i+'a')}, 0, 1);
+ System.err.println("WRITE>>"+(char)(i+'a'));
+ }
+ for(int i = 0; i < 26; i++) {
+ byte[] buffer = new byte[1];
+ assertEquals(queue.read(buffer, 0, 1), 1);
+ System.err.println("READ>>"+((char)buffer[0]));
+ assertEquals(buffer[0], (byte)(i+'a'));
+ }*/
+ }
+
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ArrayByteQueue.java b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ArrayByteQueue.java
new file mode 100644
index 0000000..893ae80
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ArrayByteQueue.java
@@ -0,0 +1,100 @@
+package org.simpleframework.common.buffer.queue;
+
+import java.io.IOException;
+
+import org.simpleframework.common.buffer.BufferException;
+
+public class ArrayByteQueue implements ByteQueue {
+
+ private byte[] buffer;
+ private int limit;
+ private int count;
+ private int seek;
+ private boolean closed;
+
+ public ArrayByteQueue(int limit) {
+ this.buffer = new byte[16];
+ this.limit = limit;
+ }
+
+ public synchronized void write(byte[] array) throws IOException {
+ write(array, 0, array.length);
+ }
+
+ public synchronized void write(byte[] array, int off, int size) throws IOException {
+ if(closed) {
+ throw new BufferException("Queue has been closed");
+ }
+ if (size + count > buffer.length) {
+ expand(count + size);
+ }
+ int fragment = buffer.length - seek; // from read pos to end
+ int space = fragment - count; // space at end
+
+ if(space >= size) {
+ System.arraycopy(array, off, buffer, seek + count, size);
+ } else {
+ int chunk = Math.min(fragment, count);
+
+ System.arraycopy(buffer, seek, buffer, 0, chunk); // adjust downward
+ System.arraycopy(array, off, buffer, chunk, size);
+ seek = 0;
+ }
+ notify();
+ count += size;
+ }
+
+ public synchronized int read(byte[] array) throws IOException {
+ return read(array, 0, array.length);
+ }
+
+ public synchronized int read(byte[] array, int off, int size) throws IOException {
+ while(count == 0) {
+ try {
+ if(closed) {
+ return -1;
+ }
+ wait();
+ } catch(Exception e) {
+ throw new BufferException("Thread interrupted", e);
+ }
+ }
+ int chunk = Math.min(size, count);
+
+ if(chunk > 0) {
+ System.arraycopy(buffer, seek, array, off, chunk);
+ seek += chunk;
+ count -= chunk;
+ }
+ return chunk;
+ }
+
+ private synchronized void expand(int capacity) throws IOException {
+ if (capacity > limit) {
+ throw new BufferException("Capacity limit %s exceeded", limit);
+ }
+ int resize = buffer.length * 2;
+ int size = Math.max(capacity, resize);
+ byte[] temp = new byte[size];
+
+ System.arraycopy(buffer, seek, temp, 0, count);
+ buffer = temp;
+ seek = 0;
+ }
+
+ public synchronized void reset() throws IOException {
+ if(closed) {
+ throw new BufferException("Queue has been closed");
+ }
+ seek = 0;
+ count = 0;
+ }
+
+ public synchronized int available() {
+ return count;
+ }
+
+ public synchronized void close() {
+ closed = true;
+ }
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ArrayByteQueueTest.java b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ArrayByteQueueTest.java
new file mode 100644
index 0000000..7d361f3
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ArrayByteQueueTest.java
@@ -0,0 +1,119 @@
+package org.simpleframework.common.buffer.queue;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+import junit.framework.TestCase;
+
+public class ArrayByteQueueTest extends TestCase {
+
+ public void testArrayByteQueue() throws Exception {
+ ArrayByteQueue queue = new ArrayByteQueue(10);
+
+ for(int i = 0; i < 9; i++) {
+ queue.write(new byte[]{(byte)('A'+i)});
+ }
+ for(int i = 0; i < 9; i++) {
+ byte[] b = new byte[1];
+ queue.read(b);
+ System.err.write(b);
+ System.err.println();
+ }
+ for(int i = 9; i < 19; i++) {
+ queue.write(new byte[]{(byte)('A'+i)});
+ }
+ for(int i = 0; i < 9; i++) {
+ byte[] b = new byte[1];
+ queue.read(b);
+ System.err.write(b);
+ System.err.println();
+ }
+ }
+
+ public void testRandomReadWrite() throws Exception {
+ ArrayByteQueue queue = new ArrayByteQueue(1024 * 10);
+
+ for(int i = 0; i < 100; i++) {
+ String text = "Test: "+i;
+ queue.write(text.getBytes());
+ }
+ for(int i = 0; i < 100; i++) {
+ String text = "Test: "+i;
+ byte[] buffer = new byte[256];
+ int size = queue.read(buffer, 0, text.length());
+ String result = new String(buffer, 0, size);
+ System.err.println(result);
+ assertEquals(result, text);
+ }
+ }
+ /*
+ public void testStream() throws Exception {
+ final ByteArrayOutputStream output = new ByteArrayOutputStream();
+ final ArrayByteQueue queue = new ArrayByteQueue(1024 * 10);
+ final Thread reader = new Thread(new Runnable() {
+ public void run() {
+ try {
+ for(int i = 0; i < 100; i++) {
+ byte[] chunk = new byte[(int)Math.round((Math.random() * 100))];
+ int size = queue.read(chunk);
+ output.write(chunk, 0, size);
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ final Thread writer = new Thread(new Runnable() {
+ public void run() {
+ try {
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ ObjectOutputStream objectOutput = new ObjectOutputStream(buffer);
+
+ for(int i = 0; i < 100; i++) {
+ try {
+ TestMessage message = new TestMessage(i, "Test Message: " +i);
+ objectOutput.writeObject(message);
+ objectOutput.flush();
+ byte[] messageBytes = buffer.toByteArray();
+ queue.write(messageBytes);
+ buffer.reset(); // clear out the buffer so toByteArray picks up changes only
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }catch(Exception e){
+ e.printStackTrace();
+ }
+ }
+ });
+ writer.start();
+ reader.start();
+ writer.join();
+ Thread.sleep(5000);
+ reader.interrupt();
+ reader.join();
+
+ ByteArrayInputStream input = new ByteArrayInputStream(output.toByteArray());
+ ObjectInputStream objectInput = new ObjectInputStream(input);
+
+ for(int i = 0; i < 100; i++) {
+ TestMessage message = (TestMessage)objectInput.readObject();
+ assertEquals(message.count, i);
+ assertEquals(message.text, "Test Message: "+i);
+ }
+ }
+*/
+ private static class TestMessage implements Serializable {
+
+ public final int count;
+ public final String text;
+
+ public TestMessage(int count, String text) {
+ this.count = count;
+ this.text = text;
+ }
+ }
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/BufferQueue.java b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/BufferQueue.java
new file mode 100644
index 0000000..5f3e97f
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/BufferQueue.java
@@ -0,0 +1,67 @@
+package org.simpleframework.common.buffer.queue;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.simpleframework.common.buffer.ArrayBuffer;
+import org.simpleframework.common.buffer.Buffer;
+
+public class BufferQueue implements Buffer {
+
+ private final ByteQueue queue;
+ private final Buffer buffer;
+
+ public BufferQueue(ByteQueue queue) {
+ this.buffer = new ArrayBuffer();
+ this.queue = queue;
+ }
+
+ public InputStream open() throws IOException {
+ return new ByteQueueStream(queue);
+ }
+
+ public Buffer allocate() throws IOException {
+ return new BufferQueue(queue);
+ }
+
+ public String encode() throws IOException {
+ return encode("UTF-8");
+ }
+
+ public String encode(String charset) throws IOException {
+ InputStream source = open();
+ byte[] chunk = new byte[512];
+ int count = 0;
+
+ while((count = source.read(chunk)) != -1) {
+ buffer.append(chunk, 0, count);
+ }
+ return buffer.encode(charset);
+ }
+
+ public Buffer append(byte[] array) throws IOException {
+ if(array.length > 0) {
+ queue.write(array);
+ }
+ return this;
+ }
+
+ public Buffer append(byte[] array, int off, int len) throws IOException {
+ if(len > 0) {
+ queue.write(array, off, len);
+ }
+ return this;
+ }
+
+ public void clear() throws IOException {
+ queue.reset();
+ }
+
+ public void close() throws IOException {
+ queue.close();
+ }
+
+ public long length() {
+ return buffer.length();
+ }
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/BufferQueueTest.java b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/BufferQueueTest.java
new file mode 100644
index 0000000..22eaba7
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/BufferQueueTest.java
@@ -0,0 +1,44 @@
+package org.simpleframework.common.buffer.queue;
+
+import java.io.InputStream;
+
+import junit.framework.TestCase;
+
+public class BufferQueueTest extends TestCase {
+
+ public void testBufferQueue() throws Exception {
+ final ByteQueue queue = new ArrayByteQueue(1024 * 1000);
+ final BufferQueue buffer = new BufferQueue(queue);
+
+ Thread reader = new Thread(new Runnable() {
+ public void run() {
+ try {
+ InputStream source = buffer.open();
+ for(int i = 0; i < 1000; i++) {
+ int octet = source.read();
+ System.err.write(octet);
+ System.err.flush();
+ }
+ }catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ Thread writer = new Thread(new Runnable() {
+ public void run() {
+ try {
+ for(int i = 0; i < 1000; i++) {
+ buffer.append(("Test message: "+i+"\n").getBytes());
+ }
+ }catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ reader.start();
+ writer.start();
+ reader.join();
+ writer.join();
+ }
+
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ByteQueue.java b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ByteQueue.java
new file mode 100644
index 0000000..dc567e9
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ByteQueue.java
@@ -0,0 +1,13 @@
+package org.simpleframework.common.buffer.queue;
+
+import java.io.IOException;
+
+public interface ByteQueue {
+ void write(byte[] array) throws IOException;
+ void write(byte[] array, int off, int size) throws IOException;
+ int read(byte[] array) throws IOException;
+ int read(byte[] array, int off, int size) throws IOException;
+ int available() throws IOException;
+ void reset() throws IOException;
+ void close() throws IOException;
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ByteQueueStream.java b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ByteQueueStream.java
new file mode 100644
index 0000000..dbf73e1
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/buffer/queue/ByteQueueStream.java
@@ -0,0 +1,40 @@
+package org.simpleframework.common.buffer.queue;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class ByteQueueStream extends InputStream {
+
+ private final ByteQueue queue;
+
+ public ByteQueueStream(ByteQueue queue) {
+ this.queue = queue;
+ }
+
+ @Override
+ public int read() throws IOException {
+ byte[] array = new byte[1];
+ int count = read(array) ;
+
+ if(count != -1) {
+ return array[0] & 0xff;
+ }
+ return -1;
+ }
+
+ public int read(byte[] buffer) throws IOException {
+ return queue.read(buffer, 0, buffer.length);
+ }
+
+ public int read(byte[] buffer, int off, int size) throws IOException {
+ return queue.read(buffer, off, size);
+ }
+
+ public int available() throws IOException {
+ return queue.available();
+ }
+
+ public void close() throws IOException {
+ queue.close();
+ }
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/lease/ContractQueueTest.java b/simple/simple-common/src/test/java/org/simpleframework/common/lease/ContractQueueTest.java
new file mode 100644
index 0000000..6fa55c1
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/lease/ContractQueueTest.java
@@ -0,0 +1,57 @@
+package org.simpleframework.common.lease;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.simpleframework.common.lease.Contract;
+import org.simpleframework.common.lease.ContractQueue;
+import org.simpleframework.common.lease.Expiration;
+
+public class ContractQueueTest extends TimeTestCase {
+
+ public void testTimeUnits() throws Exception {
+ ContractQueue<Long> queue = new ContractQueue<Long>();
+ List<String> complete = new ArrayList<String>();
+
+ for(long i = 0; i < 10000; i++) {
+ long random = (long)(Math.random() * 1000);
+ Contract<Long> contract = new Expiration(random, random, TimeUnit.NANOSECONDS);
+
+ queue.offer(contract);
+ }
+ for(int i = 0; i < 10000; i++) {
+ Contract<Long> contract = queue.take();
+
+ assertGreaterThanOrEqual(contract.getDelay(TimeUnit.NANOSECONDS), contract.getDelay(TimeUnit.NANOSECONDS));
+ assertGreaterThanOrEqual(contract.getDelay(TimeUnit.MILLISECONDS), contract.getDelay(TimeUnit.MILLISECONDS));
+ assertGreaterThanOrEqual(contract.getDelay(TimeUnit.SECONDS), contract.getDelay(TimeUnit.SECONDS));
+
+ long nanoseconds = contract.getDelay(TimeUnit.NANOSECONDS);
+ long milliseconds = contract.getDelay(TimeUnit.MILLISECONDS);
+
+ complete.add(String.format("index=[%s] nano=[%s] milli=[%s]", i, nanoseconds, milliseconds));
+ }
+ for(int i = 0; i < 10000; i++) {
+ System.err.println("expiry=[" + complete.get(i)+ "]");
+ }
+ }
+
+ public void testAccuracy() throws Exception {
+ ContractQueue<Long> queue = new ContractQueue<Long>();
+
+ for(long i = 0; i < 10000; i++) {
+ long random = (long)(Math.random() * 1000);
+ Contract<Long> contract = new Expiration(random, random, TimeUnit.NANOSECONDS);
+
+ queue.offer(contract);
+ }
+ for(int i = 0; i < 10000; i++) {
+ Contract<Long> contract = queue.take();
+
+ assertLessThanOrEqual(-2000, contract.getDelay(TimeUnit.MILLISECONDS));
+ }
+ }
+
+}
+
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/lease/ContractTest.java b/simple/simple-common/src/test/java/org/simpleframework/common/lease/ContractTest.java
new file mode 100644
index 0000000..1cc40af
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/lease/ContractTest.java
@@ -0,0 +1,40 @@
+package org.simpleframework.common.lease;
+
+import java.util.concurrent.TimeUnit;
+
+import org.simpleframework.common.lease.Contract;
+import org.simpleframework.common.lease.Expiration;
+
+public class ContractTest extends TimeTestCase {
+
+ public void testContract() throws Exception {
+ Contract ten = new Expiration(this, 10, TimeUnit.MILLISECONDS);
+ Contract twenty = new Expiration(this, 20, TimeUnit.MILLISECONDS);
+ Contract thirty= new Expiration(this, 30, TimeUnit.MILLISECONDS);
+
+ assertGreaterThanOrEqual(twenty.getDelay(TimeUnit.NANOSECONDS), ten.getDelay(TimeUnit.NANOSECONDS));
+ assertGreaterThanOrEqual(thirty.getDelay(TimeUnit.NANOSECONDS), twenty.getDelay(TimeUnit.NANOSECONDS));
+
+ assertGreaterThanOrEqual(twenty.getDelay(TimeUnit.MILLISECONDS), ten.getDelay(TimeUnit.MILLISECONDS));
+ assertGreaterThanOrEqual(thirty.getDelay(TimeUnit.MILLISECONDS), twenty.getDelay(TimeUnit.MILLISECONDS));
+
+ ten.setDelay(0, TimeUnit.MILLISECONDS);
+ twenty.setDelay(0, TimeUnit.MILLISECONDS);
+
+ assertLessThanOrEqual(ten.getDelay(TimeUnit.MILLISECONDS), 0);
+ assertLessThanOrEqual(twenty.getDelay(TimeUnit.MILLISECONDS), 0);
+
+ ten.setDelay(10, TimeUnit.MILLISECONDS);
+ twenty.setDelay(20, TimeUnit.MILLISECONDS);
+ thirty.setDelay(30, TimeUnit.MILLISECONDS);
+
+ assertGreaterThanOrEqual(twenty.getDelay(TimeUnit.NANOSECONDS), ten.getDelay(TimeUnit.NANOSECONDS));
+ assertGreaterThanOrEqual(thirty.getDelay(TimeUnit.NANOSECONDS), twenty.getDelay(TimeUnit.NANOSECONDS));
+
+ assertGreaterThanOrEqual(twenty.getDelay(TimeUnit.MILLISECONDS), ten.getDelay(TimeUnit.MILLISECONDS));
+ assertGreaterThanOrEqual(thirty.getDelay(TimeUnit.MILLISECONDS), twenty.getDelay(TimeUnit.MILLISECONDS));
+
+ ten.setDelay(0, TimeUnit.MILLISECONDS);
+ twenty.setDelay(0, TimeUnit.MILLISECONDS);
+ }
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/lease/LeaseManagerTest.java b/simple/simple-common/src/test/java/org/simpleframework/common/lease/LeaseManagerTest.java
new file mode 100644
index 0000000..9ce2b93
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/lease/LeaseManagerTest.java
@@ -0,0 +1,227 @@
+package org.simpleframework.common.lease;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.simpleframework.common.lease.Cleaner;
+import org.simpleframework.common.lease.Lease;
+import org.simpleframework.common.lease.LeaseManager;
+
+public class LeaseManagerTest extends TimeTestCase {
+
+ private static int ITERATIONS = 1000;
+ private static int MAXIMUM = 20000;
+
+ static {
+ String value = System.getProperty("iterations");
+
+ if (value != null) {
+ ITERATIONS = Integer.parseInt(value);
+ }
+ }
+
+ public void testClock() {
+ List<Long> timeList = new ArrayList<Long>();
+
+ for(int i = 0; i < ITERATIONS; i++) {
+ long time = System.nanoTime();
+ long milliseconds = TimeUnit.MILLISECONDS.convert(time, TimeUnit.MILLISECONDS);
+
+ timeList.add(milliseconds);
+ }
+ for(int i = 1; i < ITERATIONS; i++) {
+ assertLessThanOrEqual(timeList.get(i - 1), timeList.get(i));
+ }
+ }
+
+ public void testRandom() {
+ for(int i = 0; i < ITERATIONS; i++) {
+ long randomTime = getRandomTime(MAXIMUM);
+
+ assertGreaterThanOrEqual(MAXIMUM, randomTime);
+ assertGreaterThanOrEqual(randomTime, 0);
+ }
+ }
+
+ public void testOrder() throws Exception {
+ final BlockingQueue<Integer> clean = new LinkedBlockingQueue<Integer>();
+ final ConcurrentHashMap<Integer, Long> record = new ConcurrentHashMap<Integer, Long>();
+
+ Cleaner<Integer> cleaner = new Cleaner<Integer>() {
+
+ long start = System.currentTimeMillis();
+
+ public void clean(Integer key) {
+ record.put(key, start - System.currentTimeMillis());
+ clean.offer(key);
+
+ }
+ };
+ LeaseManager<Integer> manager = new LeaseManager<Integer>(cleaner);
+ List<Lease<Integer>> list = new ArrayList<Lease<Integer>>();
+
+ long start = System.currentTimeMillis();
+
+ for(int i = 0; i < ITERATIONS; i++) {
+ long randomTime = getRandomTime(MAXIMUM) + MAXIMUM + i * 50;
+
+ System.err.printf("leasing [%s] for [%s] @ %s%n", i, randomTime, System.currentTimeMillis() - start);
+
+ Lease<Integer> lease = manager.lease(i, randomTime, TimeUnit.MILLISECONDS);
+
+ list.add(lease);
+ }
+ start = System.currentTimeMillis();
+
+ for(int i = 0; i < ITERATIONS; i++) {
+ try {
+ System.err.printf("renewing [%s] for [%s] expires [%s] @ %s expired [%s] %n", i, i, list.get(i).getExpiry(TimeUnit.MILLISECONDS), System.currentTimeMillis() - start, record.get(i));
+ list.get(i).renew(i, TimeUnit.MILLISECONDS);
+ }catch(Exception e) {
+ System.err.printf("Lease %s in error: ", i);
+ e.printStackTrace(System.err);
+ }
+ }
+ int variation = 20;
+ int cleaned = 0;
+
+ for(int i = 0; i < ITERATIONS; i++) {
+ int value = clean.take();
+ cleaned++;
+
+ System.err.printf("index=[%s] clean=[%s] expiry[%s]=%s expiry[%s]=%s%n ", i, value, i, record.get(i), value, record.get(value));
+ assertLessThanOrEqual(i - variation, value);
+ }
+ assertEquals(cleaned, ITERATIONS);
+ }
+
+ public void testLease() throws Exception {
+ final BlockingQueue<Expectation> clean = new LinkedBlockingQueue<Expectation>();
+
+ Cleaner<Expectation> cleaner = new Cleaner<Expectation>() {
+ public void clean(Expectation key) {
+ clean.offer(key);
+ }
+ };
+ final BlockingQueue<Lease<Expectation>> renewalQueue = new LinkedBlockingQueue<Lease<Expectation>>();
+ final BlockingQueue<Lease<Expectation>> expiryQueue = new LinkedBlockingQueue<Lease<Expectation>>();
+ final CountDownLatch ready = new CountDownLatch(21);
+ final AtomicInteger renewCount = new AtomicInteger(ITERATIONS);
+
+ for(int i = 0; i < 20; i++) {
+ new Thread(new Runnable() {
+ public void run() {
+ while(renewCount.getAndDecrement() > 0) {
+ long randomTime = getRandomTime(MAXIMUM);
+
+ try {
+ ready.countDown();
+ ready.await();
+
+ Lease<Expectation> lease = renewalQueue.take();
+
+ try {
+ lease.renew(randomTime, TimeUnit.MILLISECONDS);
+ lease.getKey().setExpectation(randomTime, TimeUnit.MILLISECONDS);
+
+ assertGreaterThanOrEqual(randomTime, 0);
+ assertGreaterThanOrEqual(randomTime, lease.getExpiry(TimeUnit.MILLISECONDS));
+ } catch(Exception e) {
+ expiryQueue.offer(lease);
+ }
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ }).start();
+ }
+ final LeaseManager<Expectation> manager = new LeaseManager<Expectation>(cleaner);
+ final CountDownLatch latch = new CountDownLatch(21);
+ final AtomicInteger leaseCount = new AtomicInteger(ITERATIONS);
+
+ for(int i = 0; i < 20; i++) {
+ new Thread(new Runnable() {
+ public void run() {
+ while(leaseCount.getAndDecrement() > 0) {
+ long randomTime = getRandomTime(MAXIMUM);
+ Expectation expectation = new Expectation(randomTime, TimeUnit.MILLISECONDS);
+
+ try {
+ latch.countDown();
+ latch.await();
+ } catch(InterruptedException e) {
+ e.printStackTrace();
+ }
+ assertGreaterThanOrEqual(randomTime, 0);
+
+ Lease<Expectation> lease = manager.lease(expectation, randomTime, TimeUnit.MILLISECONDS);
+ renewalQueue.offer(lease);
+ }
+ }
+ }).start();
+ }
+ ready.countDown();
+ latch.countDown();
+
+ for (int i = 0; i < ITERATIONS; i++) {
+ Expectation expectation = clean.poll(MAXIMUM, TimeUnit.MILLISECONDS);
+
+ if(expectation != null) {
+ long accuracy = System.nanoTime() - expectation.getExpectation(TimeUnit.NANOSECONDS);
+ long milliseconds = TimeUnit.MILLISECONDS.convert(accuracy, TimeUnit.NANOSECONDS);
+
+ System.err.printf("index=[%s] accuracy=[%s] queue=[%s]%n", i, milliseconds, clean.size());
+ } else {
+ System.err.printf("index=[%s] queue=[%s]%n", i, clean.size());
+ }
+
+ }
+ System.err.printf("waiting=[%s]%n", clean.size());
+ }
+
+
+ public static class Expectation {
+
+ private long time;
+
+ public Expectation(long duration, TimeUnit unit) {
+ setExpectation(duration, unit);
+ }
+
+ public void setExpectation(long duration, TimeUnit unit) {
+ long nano = TimeUnit.NANOSECONDS.convert(duration, unit);
+ long expect = nano + System.nanoTime();
+
+ this.time = expect;
+ }
+
+ public long getExpectation(TimeUnit unit) {
+ return unit.convert(time, TimeUnit.NANOSECONDS);
+ }
+ }
+
+
+ public static long getRandomTime(long maximum) {
+ long random = new Random().nextLong() % maximum;
+
+ if(random < 0) {
+ random *= -1;
+ }
+ return random;
+ }
+
+ public static void main(String[] list) throws Exception {
+ new LeaseManagerTest().testClock();
+ new LeaseManagerTest().testRandom();
+ new LeaseManagerTest().testOrder();
+ new LeaseManagerTest().testLease();
+ }
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/lease/LeaseTest.java b/simple/simple-common/src/test/java/org/simpleframework/common/lease/LeaseTest.java
new file mode 100644
index 0000000..d4b73d7
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/lease/LeaseTest.java
@@ -0,0 +1,87 @@
+package org.simpleframework.common.lease;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import org.simpleframework.common.lease.Cleaner;
+import org.simpleframework.common.lease.Contract;
+import org.simpleframework.common.lease.ContractController;
+import org.simpleframework.common.lease.ContractLease;
+import org.simpleframework.common.lease.ContractMaintainer;
+import org.simpleframework.common.lease.Expiration;
+import org.simpleframework.common.lease.Lease;
+
+public class LeaseTest extends TimeTestCase {
+
+ private static int ITERATIONS = 10000;
+
+ static {
+ String value = System.getProperty("iterations");
+
+ if (value != null) {
+ ITERATIONS = Integer.parseInt(value);
+ }
+ }
+
+ public void testLease() throws Exception {
+ final BlockingQueue<Integer> clean = new LinkedBlockingQueue<Integer>();
+
+ Cleaner<Integer> cleaner = new Cleaner<Integer>() {
+ public void clean(Integer key) {
+ clean.offer(key);
+ }
+ };
+ Map<Integer, Contract> table = new ConcurrentHashMap<Integer, Contract>();
+ List<Lease> list = new ArrayList<Lease>();
+ ContractController controller = new ContractMaintainer(cleaner);
+
+ for (int i = 0; i < ITERATIONS; i++) {
+ long random = (long) (Math.random() * 1000) + 1000L;
+ Contract<Integer> contract = new Expiration(i, random, TimeUnit.MILLISECONDS);
+ Lease lease = new ContractLease(controller, contract);
+
+ table.put(i, contract);
+ list.add(lease);
+ controller.issue(contract);
+ }
+ for (int i = 0; i < ITERATIONS; i++) {
+ long random = (long) (Math.random() * 1000);
+
+ try {
+ list.get(i).renew(random, TimeUnit.MILLISECONDS);
+ } catch (Exception e) {
+ continue;
+ // e.printStackTrace();
+ }
+ }
+ for (int i = 0; i < ITERATIONS; i++) {
+ try {
+ System.err.println("delay: "
+ + list.get(i).getExpiry(TimeUnit.MILLISECONDS));
+ } catch (Exception e) {
+ continue;
+ // e.printStackTrace();
+ }
+ }
+ System.err.println("clean: " + clean.size());
+
+ for (int i = 0; i < ITERATIONS; i++) {
+ Integer index = clean.take();
+ Contract contract = table.get(index);
+
+ // assertLessThanOrEqual(-4000,
+ // contract.getDelay(TimeUnit.MILLISECONDS));
+ System.err.println(String.format("index=[%s] delay=[%s]", index,
+ contract.getDelay(TimeUnit.MILLISECONDS)));
+ }
+ }
+
+ public static void main(String[] list) throws Exception {
+ new LeaseTest().testLease();
+ }
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/lease/TimeTestCase.java b/simple/simple-common/src/test/java/org/simpleframework/common/lease/TimeTestCase.java
new file mode 100644
index 0000000..294cc9b
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/lease/TimeTestCase.java
@@ -0,0 +1,25 @@
+package org.simpleframework.common.lease;
+
+import junit.framework.TestCase;
+
+public class TimeTestCase extends TestCase {
+
+ public void testTime() {
+ }
+
+ public static void assertLessThan(long a, long b) {
+ assertTrue(String.format("Value %s is not less than %s", a, b), a < b);
+ }
+
+ public static void assertLessThanOrEqual(long a, long b) {
+ assertTrue(String.format("Value %s is not less than or equal to %s", a, b), a <= b);
+ }
+
+ public static void assertGreaterThan(long a, long b) {
+ assertTrue(String.format("Value %s is not greater than %s", a, b), a > b);
+ }
+
+ public static void assertGreaterThanOrEqual(long a, long b) {
+ assertTrue(String.format("Value %s is not greater than or equal to %s", a, b), a >= b);
+ }
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/thread/SchedulerTest.java b/simple/simple-common/src/test/java/org/simpleframework/common/thread/SchedulerTest.java
new file mode 100644
index 0000000..78fe802
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/thread/SchedulerTest.java
@@ -0,0 +1,65 @@
+package org.simpleframework.common.thread;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import org.simpleframework.common.thread.ConcurrentScheduler;
+
+import junit.framework.TestCase;
+
+public class SchedulerTest extends TestCase {
+
+ private static final int ITERATIONS = 10000;
+
+ public void testScheduler() throws Exception {
+ ConcurrentScheduler queue = new ConcurrentScheduler(Runnable.class, 10);
+ LinkedBlockingQueue<Timer> list = new LinkedBlockingQueue<Timer>();
+
+ for(int i = 0; i < ITERATIONS; i++) {
+ queue.execute(new Task(list, new Timer(i)), i, TimeUnit.MILLISECONDS);
+ }
+ for(Timer timer = list.take(); timer.getValue() < ITERATIONS - 10; timer = list.take()) {
+ System.err.println("value=["+timer.getValue()+"] delay=["+timer.getDelay()+"] expect=["+timer.getExpectation()+"]");
+ }
+ }
+
+ public class Timer {
+
+ private Integer value;
+
+ private long time;
+
+ public Timer(Integer value) {
+ this.time = System.currentTimeMillis();
+ this.value = value;
+ }
+
+ public Integer getValue() {
+ return value;
+ }
+
+ public long getDelay() {
+ return System.currentTimeMillis() - time;
+ }
+
+ public int getExpectation() {
+ return value.intValue();
+ }
+ }
+
+ public class Task implements Runnable {
+
+ private LinkedBlockingQueue<Timer> queue;
+
+ private Timer timer;
+
+ public Task(LinkedBlockingQueue<Timer> queue, Timer timer) {
+ this.queue = queue;
+ this.timer = timer;
+ }
+
+ public void run() {
+ queue.offer(timer);
+ }
+ }
+}
diff --git a/simple/simple-common/src/test/java/org/simpleframework/common/thread/TransientApplication.java b/simple/simple-common/src/test/java/org/simpleframework/common/thread/TransientApplication.java
new file mode 100644
index 0000000..69941b2
--- /dev/null
+++ b/simple/simple-common/src/test/java/org/simpleframework/common/thread/TransientApplication.java
@@ -0,0 +1,54 @@
+package org.simpleframework.common.thread;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.simpleframework.common.thread.ConcurrentExecutor;
+
+public class TransientApplication {
+
+ public static void main(String[] list) throws Exception {
+ BlockingQueue queue = new LinkedBlockingQueue();
+ ConcurrentExecutor pool = new ConcurrentExecutor(TerminateTask.class, 10);
+
+ for(int i = 0; i < 50; i++) {
+ pool.execute(new LongTask(queue, String.valueOf(i)));
+ }
+ pool.execute(new TerminateTask(pool));
+ }
+
+ private static class TerminateTask implements Runnable {
+
+ private ConcurrentExecutor pool;
+
+ public TerminateTask(ConcurrentExecutor pool) {
+ this.pool = pool;
+ }
+
+ public void run() {
+ pool.stop();
+ }
+ }
+
+ private static class LongTask implements Runnable {
+
+ private BlockingQueue queue;
+
+ private String name;
+
+ public LongTask(BlockingQueue queue, String name) {
+ this.queue = queue;
+ this.name = name;
+ }
+
+ public void run() {
+ try {
+ Thread.sleep(1000);
+ } catch(Exception e) {
+ e.printStackTrace();
+ }
+ System.err.println(name);
+ queue.offer(name);
+ }
+ }
+}