You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ma...@apache.org on 2009/06/27 17:53:26 UTC

svn commit: r788992 [22/25] - in /incubator/ace/trunk: gateway/ gateway/src/ gateway/src/net/ gateway/src/net/luminis/ gateway/src/net/luminis/liq/ gateway/src/net/luminis/liq/bootstrap/ gateway/src/net/luminis/liq/bootstrap/multigateway/ gateway/src/n...

Added: incubator/ace/trunk/test/src/net/luminis/liq/gateway/log/task/LogSyncTaskTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/gateway/log/task/LogSyncTaskTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/gateway/log/task/LogSyncTaskTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/gateway/log/task/LogSyncTaskTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,134 @@
+package net.luminis.liq.gateway.log.task;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Properties;
+
+import net.luminis.liq.discovery.Discovery;
+import net.luminis.liq.gateway.log.store.LogStore;
+import net.luminis.liq.identification.Identification;
+import net.luminis.liq.log.LogDescriptor;
+import net.luminis.liq.log.LogEvent;
+import net.luminis.liq.repository.SortedRangeSet;
+import net.luminis.liq.test.utils.TestUtils;
+
+import org.osgi.service.log.LogService;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class LogSyncTaskTest {
+
+    private LogSyncTask m_task;
+
+    @BeforeMethod(alwaysRun = true)
+    protected void setUp() throws Exception {
+        m_task = new LogSyncTask("testlog");
+        TestUtils.configureObject(m_task, LogService.class);
+        TestUtils.configureObject(m_task, Identification.class);
+        TestUtils.configureObject(m_task, Discovery.class);
+        TestUtils.configureObject(m_task, LogStore.class);
+    }
+
+    @Test(groups = { UNIT })
+    public synchronized void getRange() throws Exception {
+        final LogDescriptor range = new LogDescriptor("gwID", 1, new SortedRangeSet("1-10"));
+        m_task.getDescriptor(new InputStream() {
+            int m_count = 0;
+            byte[] m_bytes = (range.toRepresentation() + "\n").getBytes();
+            @Override
+            public int read() throws IOException {
+                if (m_count < m_bytes.length) {
+                    byte b = m_bytes[m_count];
+                    m_count++;
+                    return b;
+                } else {
+                    return -1;
+                }
+            }
+        });
+    }
+
+    @Test(groups = { UNIT })
+    public synchronized void synchronizeLog() throws Exception {
+        final LogDescriptor range = new LogDescriptor("gwID", 1, new SortedRangeSet(new long[] {0}));
+        final LogEvent event = new LogEvent("gwID", 1, 1, 1, 1, new Properties());
+        final List<LogEvent> events = new ArrayList<LogEvent>();
+        events.add(event);
+
+        InputStream input = new InputStream() {
+            byte[] bytes = range.toRepresentation().getBytes();
+            int count = 0;
+            @Override
+            public int read() throws IOException {
+                if (count < bytes.length) {
+                    byte b = bytes[count];
+                    count++;
+                    return b;
+                } else {
+                    return -1;
+                }
+            }
+        };
+        TestUtils.configureObject(m_task, LogStore.class, new LogStore() {
+            public List<?> get(long logID, long from, long to) throws IOException {
+                return events;
+            }
+            public long getHighestID(long logID) throws IOException {
+                return event.getID();
+            }
+            public List<?> get(long logID) throws IOException { return null; }
+            public long[] getLogIDs() throws IOException { return null; }
+            @SuppressWarnings("unchecked")
+            public LogEvent put(int type, Dictionary props) throws IOException { return null; }
+        });
+        MockConnection connection = new MockConnection(new URL("http://mock"));
+        m_task.synchronizeLog(1, input, connection);
+        String expectedString = event.toRepresentation() + "\n";
+        String actualString = connection.getString();
+
+        assert actualString.equals(expectedString) : "We expected " + expectedString + " but received " + actualString;
+    }
+
+    private class MockConnection extends Connection {
+
+        private MockOutputStream m_output;
+
+        public MockConnection(URL url) throws IOException {
+            super(url);
+            m_output = new MockOutputStream();
+        }
+
+        public String getString() {
+            return m_output.getString();
+        }
+
+        @Override
+        public OutputStream getOutputStream() throws IOException {
+            return m_output;
+        }
+
+
+    }
+
+    private class MockOutputStream extends OutputStream {
+        byte[] bytes = new byte[8*1024];
+        int count = 0;
+        @Override
+        public void write(int arg0) throws IOException {
+            bytes[count] = (byte) arg0;
+            count++;
+        }
+
+        public String getString() {
+            return new String(bytes, 0, count);
+        }
+    }
+
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/identification/ifconfig/IfconfigIdentificationTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/identification/ifconfig/IfconfigIdentificationTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/identification/ifconfig/IfconfigIdentificationTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/identification/ifconfig/IfconfigIdentificationTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,35 @@
+package net.luminis.liq.identification.ifconfig;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+import net.luminis.liq.test.utils.TestUtils;
+
+import org.osgi.service.log.LogService;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+public class IfconfigIdentificationTest {
+
+    private IfconfigIdentification m_identification;
+
+    @BeforeTest(alwaysRun = true)
+    protected void setUp() throws Exception {
+        m_identification = new IfconfigIdentification();
+        TestUtils.configureObject(m_identification, LogService.class);
+    }
+
+    @Test(groups = { UNIT })
+    public void testMacAddressVerifying() throws Exception {
+        assert m_identification.isValidMac("FF:FF:FF:FF:FF:FF");
+        assert m_identification.isValidMac("01:23:45:67:89:01");
+        assert m_identification.isValidMac("0D:C3:45:6A:B9:01");
+        assert !m_identification.isValidMac("");
+        assert !m_identification.isValidMac("FF:FF:FF:FF:FF");
+        assert !m_identification.isValidMac("FF:FF:FF:FF:FF:");
+        assert !m_identification.isValidMac("FF:FF:FF:FF:FF:F");
+        assert !m_identification.isValidMac("A:B:C:D:E:F");
+        assert !m_identification.isValidMac("FF:FF:FF:FF:FF:FG");
+        assert !m_identification.isValidMac("FF:FF:FF:FF:FF:FF:");
+        assert !m_identification.isValidMac("FF-FF-FF-FF-FF-FF");
+        assert !m_identification.isValidMac("thisisnotamacaddr");
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/identification/property/SimpleIdentificationTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/identification/property/SimpleIdentificationTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/identification/property/SimpleIdentificationTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/identification/property/SimpleIdentificationTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,39 @@
+package net.luminis.liq.identification.property;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.util.Properties;
+
+import net.luminis.liq.identification.property.constants.IdentificationConstants;
+import net.luminis.liq.test.utils.TestUtils;
+
+import org.osgi.service.log.LogService;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+public class SimpleIdentificationTest {
+    private PropertyBasedIdentification m_identification;
+
+    private static final String TEST_ID = "testGatewayID";
+
+    @BeforeTest(alwaysRun = true)
+    protected void setUp() throws Exception {
+        m_identification = new PropertyBasedIdentification();
+        TestUtils.configureObject(m_identification, LogService.class);
+    }
+
+    /**
+     * Test simple identification
+     *
+     * @throws Exception
+     */
+    @SuppressWarnings("serial")
+    @Test(groups = { UNIT })
+    public void testSimpleIdentification() throws Exception {
+        m_identification.updated(
+            new Properties() {
+                {put(IdentificationConstants.IDENTIFICATION_GATEWAYID_KEY, TEST_ID);}
+            });
+        assert TEST_ID.equals(m_identification.getID()) : "gateway ID does not match configured gateway ID";
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/log/LogDescriptorTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/log/LogDescriptorTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/log/LogDescriptorTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/log/LogDescriptorTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,49 @@
+package net.luminis.liq.log;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+import net.luminis.liq.log.LogDescriptor;
+import net.luminis.liq.repository.SortedRangeSet;
+
+import org.testng.annotations.Test;
+
+public class LogDescriptorTest {
+
+    @Test(groups = { UNIT })
+    public void serializeDescriptor() {
+        LogDescriptor descriptor = new LogDescriptor("gwid", 1, new SortedRangeSet("2-3"));
+        assert descriptor.toRepresentation().equals("gwid,1,2-3") : "The representation of our descriptor is incorrect:" + descriptor.toRepresentation();
+    }
+
+    @Test(groups = { UNIT })
+    public void deserializeDescriptor() {
+        LogDescriptor descriptor = new LogDescriptor("gwid,1,2-3");
+        assert descriptor.getGatewayID().equals("gwid") : "Gateway ID not correctly parsed.";
+        assert descriptor.getLogID() == 1 : "Log ID not correctly parsed.";
+        assert descriptor.getRangeSet().toRepresentation().equals("2-3") : "There should be nothing in the diff between the set in the descriptor and the check-set.";
+    }
+
+    @Test(groups = { UNIT })
+    public void deserializeMultiRangeDescriptor() {
+        LogDescriptor descriptor = new LogDescriptor("gwid,1,1-4$k6$k8$k10-20");
+        assert descriptor.getGatewayID().equals("gwid") : "Gateway ID not correctly parsed.";
+        assert descriptor.getLogID() == 1 : "Log ID not correctly parsed.";
+        String representation = descriptor.getRangeSet().toRepresentation();
+        assert representation.equals("1-4,6,8,10-20") : "There should be nothing in the diff between the set in the descriptor and the check-set, but we parsed: " + representation;
+    }
+
+    @Test(groups = { UNIT })
+    public void deserializeMultiRangeDescriptorWithFunnyGWID() {
+        String line = "gw$$id,1,1-4$k6$k8$k10-20";
+        LogDescriptor descriptor = new LogDescriptor(line);
+        assert descriptor.getGatewayID().equals("gw$id") : "Gateway ID not correctly parsed.";
+        assert descriptor.getLogID() == 1 : "Log ID not correctly parsed.";
+        assert line.equals(descriptor.toRepresentation()) : "Converting the line back to the representation failed.";
+        String representation = descriptor.getRangeSet().toRepresentation();
+        assert representation.equals("1-4,6,8,10-20") : "There should be nothing in the diff between the set in the descriptor and the check-set, but we parsed: " + representation;
+    }
+
+    @Test(groups = { UNIT }, expectedExceptions = IllegalArgumentException.class)
+    public void deserializeInvalidDescriptor() throws Exception {
+        new LogDescriptor("invalidStringRepresentation");
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/log/LogEventTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/log/LogEventTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/log/LogEventTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/log/LogEventTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,69 @@
+package net.luminis.liq.log;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.util.Dictionary;
+import java.util.Properties;
+
+import org.testng.annotations.Test;
+
+public class LogEventTest {
+    @Test(groups = { UNIT })
+    public void serializeLogEvent() {
+        LogEvent e = new LogEvent("gwid", 1, 2, 3, AuditEvent.FRAMEWORK_STARTED, new Properties());
+        assert e.toRepresentation().equals("gwid,1,2,3," + AuditEvent.FRAMEWORK_STARTED);
+        Properties p = new Properties();
+        p.put(AuditEvent.KEY_ID, "my first value");
+        e = new LogEvent("gwid", 1, 2, 3, AuditEvent.BUNDLE_INSTALLED, p);
+        assert e.toRepresentation().equals("gwid,1,2,3," + AuditEvent.BUNDLE_INSTALLED + "," + AuditEvent.KEY_ID + ",my first value");
+        e = new LogEvent("gwid,gwid\n\r$", 1, 2, 3, AuditEvent.FRAMEWORK_STARTED, new Properties());
+        assert e.toRepresentation().equals("gwid$kgwid$n$r$$,1,2,3," + AuditEvent.FRAMEWORK_STARTED);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test(groups = { UNIT })
+    public void deserializeLogEvent() {
+        LogEvent e = new LogEvent("gwid$kgwid$n$r$$,1,2,3," + AuditEvent.FRAMEWORK_STARTED + ",a,1,b,2,c,3");
+        assert e.getGatewayID().equals("gwid,gwid\n\r$") : "Gateway ID is not correctly parsed";
+        assert e.getLogID() == 1 : "Log ID is not correctly parsed";
+        assert e.getID() == 2 : "ID is not correctly parsed";
+        assert e.getTime() == 3 : "Time is not correctly parsed";
+        assert e.getType() == AuditEvent.FRAMEWORK_STARTED : "Event type is wrong";
+        Dictionary p = e.getProperties();
+        assert p != null : "Properties are not correctly parsed";
+        assert p.get("a").equals("1") : "Property a should be 1";
+        assert p.get("b").equals("2") : "Property a should be 1";
+        assert p.get("c").equals("3") : "Property a should be 1";
+    }
+    @Test(groups = { UNIT })
+    public void deserializeIllegalLogEvent() {
+        try {
+            new LogEvent("garbage in, garbage out!");
+            assert false : "Parsing garbage should result in an exception";
+        }
+        catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            new LogEvent("g$z,1,2,3," + AuditEvent.BUNDLE_STOPPED);
+            assert false : "Parsing illegal token should result in an exception";
+        }
+        catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            new LogEvent("g$,1,2,3," + AuditEvent.BUNDLE_STOPPED);
+            assert false : "Parsing half of a token should result in an exception";
+        }
+        catch (IllegalArgumentException e) {
+            // expected
+        }
+        try {
+            new LogEvent("g$,1,2,3," + AuditEvent.BUNDLE_STOPPED + ",a");
+            assert false : "Parsing only a key should result in an exception";
+        }
+        catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/log/listener/LogTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/log/listener/LogTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/log/listener/LogTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/log/listener/LogTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,150 @@
+package net.luminis.liq.log.listener;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Properties;
+
+import net.luminis.liq.log.AuditEvent;
+import net.luminis.liq.log.Log;
+import net.luminis.liq.log.listener.MockLog.LogEntry;
+import net.luminis.liq.test.utils.TestUtils;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkEvent;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class LogTest {
+
+    private LogProxy m_logProxy;
+
+    private Log m_mockLog;
+
+    @BeforeMethod(alwaysRun = true)
+    protected void setUp() throws Exception {
+        m_logProxy = new LogProxy();
+        m_mockLog = new MockLog();
+    }
+
+    /**
+     * Test whether logging to the cache and setting a new Log causes the log entries to be flushed to this new Log.
+     */
+    @SuppressWarnings("unchecked")
+    @Test(groups = { UNIT })
+    public void testLogCacheFlush() throws Exception {
+        assert ((MockLog) m_mockLog).getLogEntries().size() == 0 : "MockLog is not empty on start of test";
+
+        Dictionary props = new Properties();
+        String test = "test";
+        String value = "value";
+        props.put(test, value);
+        m_logProxy.log(1, props);
+
+        assert ((MockLog) m_mockLog).getLogEntries().size() == 0 : "MockLog is not empty, but should be as the log should be in the cache";
+
+        m_logProxy.setLog(m_mockLog);
+
+        assert ((MockLog) m_mockLog).getLogEntries().size() == 1 : "Log should contain 1 entry";
+        assert ((MockLog.LogEntry) ((MockLog) m_mockLog).getLogEntries().get(0)).getProperties().get(test).equals(value) : "The property should be 'test:value'";
+    }
+
+    /**
+     * Test whether after unsetting the Log, no new log entries are added, but that they are added to the cache instead
+     * (test the latter by flushing the cache).
+     */
+    @SuppressWarnings("unchecked")
+    @Test(groups = { UNIT })
+    public void testUnsettingLog() throws Exception {
+        assert ((MockLog) m_mockLog).getLogEntries().size() == 0 : "MockLog is not empty on start of test";
+        m_logProxy.setLog(m_mockLog);
+
+        Dictionary props = new Properties();
+        props.put("test", "value");
+        m_logProxy.log(1, props);
+
+        assert ((MockLog) m_mockLog).getLogEntries().size() == 1 : "MockLog should have 1 log entry";
+
+        m_logProxy.setLog(null);
+
+        Dictionary props2 = new Properties();
+        props2.put("test2", "value2");
+        m_logProxy.log(2, props2);
+
+        assert ((MockLog) m_mockLog).getLogEntries().size() == 1 : "MockLog should still have 1 log entry";
+
+        m_logProxy.setLog(m_mockLog);
+
+        assert ((MockLog) m_mockLog).getLogEntries().size() == 2 : "MockLog should have 2 log entries";
+    }
+
+    /**
+     * Basic functionality of the ListenerImpl is covered, the rest of the situations will probably be covered by integration
+     * tests. Note: test the deployment event INSTALL only when a BundleContext is available
+     */
+    @SuppressWarnings("unchecked")
+    @Test(groups = { UNIT })
+    public void testEventConverting() throws Exception {
+        ListenerImpl listeners = new ListenerImpl(null, m_logProxy);
+        listeners.startInternal();
+        m_logProxy.setLog(m_mockLog);
+
+        final String symbolicName = "net.luminis.liq.auditlog.listener.testbundle.a";
+        final long bundleId = 123;
+        final String bundleVersion = "1.2.3";
+        final String bundleLocation = "/home/bla/schaap/testbundlea.jar";
+
+        Bundle testBundleA = TestUtils.createMockObjectAdapter(Bundle.class, new Object() {
+            @SuppressWarnings("all")
+            public long getBundleId() {
+                return bundleId;
+            }
+
+            @SuppressWarnings("all")
+            public String getSymbolicName() {
+                return symbolicName;
+            }
+
+            @SuppressWarnings("all")
+            public Dictionary getHeaders() {
+                Dictionary dict = new Properties();
+                dict.put(Constants.BUNDLE_VERSION, bundleVersion);
+                return dict;
+            }
+
+            @SuppressWarnings("all")
+            public String getLocation() {
+                return bundleLocation;
+            }
+        });
+
+        BundleEvent bundleEvent = new BundleEvent(BundleEvent.INSTALLED, testBundleA);
+        FrameworkEvent frameworkEvent = new FrameworkEvent(FrameworkEvent.INFO, testBundleA, new IllegalStateException());
+
+        listeners.bundleChanged(bundleEvent);
+        listeners.frameworkEvent(frameworkEvent);
+        listeners.stopInternal();
+
+        List logEntries = ((MockLog) m_mockLog).getLogEntries();
+        assert logEntries.size() == 2 : "2 log entries should be logged";
+
+        LogEntry bundleEntry = (LogEntry) logEntries.get(0);
+        assert bundleEntry.getType() == AuditEvent.BUNDLE_INSTALLED : "state BUNDLE_INSTALLED (" + AuditEvent.BUNDLE_INSTALLED + ") should be in log but '" + bundleEntry.getType() + "' is in log instead";
+        Dictionary bundleProps = bundleEntry.getProperties();
+        assert bundleProps.size() == 4 : "4 properties should be stored, but found: " + bundleProps.size();
+        assert bundleProps.get(AuditEvent.KEY_ID).equals(Long.toString(bundleId)) : "id should be " + bundleId + " but is: " + bundleProps.get(AuditEvent.KEY_ID);
+        assert bundleProps.get(AuditEvent.KEY_NAME).equals(symbolicName) : "symbolicName should be " + symbolicName + " but is " + bundleProps.get(AuditEvent.KEY_NAME);
+        assert bundleProps.get(AuditEvent.KEY_VERSION).equals(bundleVersion) : "version should be " + bundleVersion + " but is " + bundleProps.get(AuditEvent.KEY_VERSION);
+        assert bundleProps.get(AuditEvent.KEY_LOCATION).equals(bundleLocation) : "location should be " + bundleLocation + " but is " + bundleProps.get(AuditEvent.KEY_LOCATION);
+
+        LogEntry frameworkEntry = (LogEntry) logEntries.get(1);
+        assert frameworkEntry.getType() == AuditEvent.FRAMEWORK_INFO : "state FRAMEWORK_INFO (" + AuditEvent.FRAMEWORK_INFO + ") should be in log but '" + frameworkEntry.getType() + "' is in log instead";
+        Dictionary frameworkProps = frameworkEntry.getProperties();
+        assert frameworkProps.size() == 2 : "2 properties should be stored, but found: " + frameworkProps.size();
+        assert frameworkProps.get(AuditEvent.KEY_ID).equals(Long.toString(bundleId)) : "id should be " + bundleId + " but is: " + frameworkProps.get(AuditEvent.KEY_ID);
+        assert frameworkProps.get(AuditEvent.KEY_TYPE).equals(IllegalStateException.class.getName()) : "exceptionType should be " + IllegalStateException.class.getName() + " but is: " + frameworkProps.get(AuditEvent.KEY_TYPE);
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/log/listener/MockLog.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/log/listener/MockLog.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/log/listener/MockLog.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/log/listener/MockLog.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,53 @@
+package net.luminis.liq.log.listener;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.List;
+
+import net.luminis.liq.log.Log;
+
+public class MockLog implements Log {
+
+    @SuppressWarnings("unchecked")
+    private List m_logEntries;
+
+    @SuppressWarnings("unchecked")
+    public MockLog() {
+        m_logEntries = Collections.synchronizedList(new ArrayList());
+    }
+
+    @SuppressWarnings("unchecked")
+    public void log(int type, Dictionary properties) {
+        m_logEntries.add(new LogEntry(type, properties));
+    }
+
+    @SuppressWarnings("unchecked")
+    public List getLogEntries() {
+        return new ArrayList(m_logEntries);
+    }
+
+    public void clear() {
+        m_logEntries.clear();
+    }
+
+    public class LogEntry {
+        private int m_type;
+        @SuppressWarnings("unchecked")
+        private Dictionary m_properties;
+        @SuppressWarnings("unchecked")
+        public LogEntry(int type, Dictionary properties) {
+            m_type = type;
+            m_properties = properties;
+        }
+
+        public int getType() {
+            return m_type;
+        }
+
+        @SuppressWarnings("unchecked")
+        public Dictionary getProperties() {
+            return m_properties;
+        }
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/obr/metadata/bindeximpl/BindexMetadataTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/obr/metadata/bindeximpl/BindexMetadataTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/obr/metadata/bindeximpl/BindexMetadataTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/obr/metadata/bindeximpl/BindexMetadataTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,81 @@
+package net.luminis.liq.obr.metadata.bindeximpl;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+
+import net.luminis.liq.deployment.provider.ArtifactData;
+import net.luminis.liq.deployment.provider.impl.ArtifactDataImpl;
+import net.luminis.liq.obr.metadata.MetadataGenerator;
+import net.luminis.liq.obr.metadata.bindex.BIndexMetadataGenerator;
+import net.luminis.liq.test.utils.deployment.BundleStreamGenerator;
+
+import org.testng.annotations.Test;
+
+public class BindexMetadataTest {
+
+    private ArtifactData generateBundle(File file, String symbolicName, String version) throws Exception {
+        ArtifactData bundle = new ArtifactDataImpl(file.getName(), symbolicName, version, file.toURI().toURL(), false);
+        BundleStreamGenerator.generateBundle(bundle);
+        return bundle;
+    }
+
+    /**
+     * Generate metadata index, verify contents
+     */
+    @Test(groups = { UNIT })
+    public void generateMetaData() throws Exception {
+        File dir = File.createTempFile("meta", "");
+        dir.delete();
+        dir.mkdir();
+        generateBundle(File.createTempFile("bundle", ".jar", dir), "bundle.symbolicname.1", "1.0.0");
+        generateBundle(File.createTempFile("bundle", ".jar", dir), "bundle.symbolicname.2", "1.0.0");
+        generateBundle(File.createTempFile("bundle", ".jar", dir), "bundle.symbolicname.3", "1.0.0");
+        MetadataGenerator meta = new BIndexMetadataGenerator();
+        meta.generateMetadata(dir);
+        File index = new File(dir, "repository.xml");
+        assert index.exists() : "No repository index was generated";
+        assert index.length() > 0 : "Repository index can not be size 0";
+        int count = 0;
+        String line;
+        BufferedReader in = new BufferedReader(new FileReader(index));
+        while ((line = in.readLine()) != null) {
+            if (line.contains("<resource")) {
+                count++;
+            }
+        }
+        in.close();
+        assert count == 3 : "Expected 3 resources in the repositoty index, found " + count + ".";
+    }
+
+    /**
+     * Generate a metadata index, remove a bundle, regenerate metadata, verify.
+     */
+    @Test(groups = { UNIT })
+    public void updateMetaData() throws Exception {
+        File dir = File.createTempFile("meta", "");
+        dir.delete();
+        dir.mkdir();
+        File bundle = File.createTempFile("bundle", ".jar", dir);
+        generateBundle(bundle, "bundle.symbolicname.1", "1.0.0");
+        MetadataGenerator meta = new BIndexMetadataGenerator();
+        meta.generateMetadata(dir);
+        bundle.delete();
+        meta.generateMetadata(dir);
+        File index = new File(dir, "repository.xml");
+        assert index.exists() : "No repository index was generated";
+        assert index.length() > 0 : "Repository index can not be size 0";
+        int count = 0;
+        String line;
+        BufferedReader in = new BufferedReader(new FileReader(index));
+        while ((line = in.readLine()) != null) {
+            if (line.contains("<resource")) {
+                count++;
+            }
+        }
+        in.close();
+        assert count == 0 : "Expected 0 resources in the repositoty index, found " + count + ".";
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/obr/servlet/BundleServletTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/obr/servlet/BundleServletTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/obr/servlet/BundleServletTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/obr/servlet/BundleServletTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,228 @@
+package net.luminis.liq.obr.servlet;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Random;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import net.luminis.liq.obr.storage.BundleStore;
+import net.luminis.liq.test.utils.FileUtils;
+import net.luminis.liq.test.utils.TestUtils;
+
+import org.osgi.service.log.LogService;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class BundleServletTest {
+
+    private HttpServletRequest m_request;
+
+    private HttpServletResponse m_response;
+
+    private ByteArrayOutputStream m_byteStream = new ByteArrayOutputStream();
+
+    protected int m_status;
+
+    private MockBundleStore m_store;
+    private BundleServlet m_bundleServlet;
+    private File m_testFile;
+    private String m_requestFile;
+
+
+    @BeforeMethod(alwaysRun = true)
+    protected void setUp() throws IOException {
+        m_testFile = createRandomFileWithContent();
+        m_store = new MockBundleStore(new FileInputStream(m_testFile));
+        m_bundleServlet = new BundleServlet();
+
+        TestUtils.configureObject(m_bundleServlet, LogService.class);
+        TestUtils.configureObject(m_bundleServlet, BundleStore.class, m_store);
+
+        m_request = TestUtils.createMockObjectAdapter(HttpServletRequest.class, new Object() {
+            @SuppressWarnings("unused")
+            public String getParameter(String param) {
+                return m_requestFile;
+            }
+
+            @SuppressWarnings("unused")
+            public String getPathInfo() {
+                return "/" + m_requestFile;
+            }
+
+            @SuppressWarnings("unused")
+            public StringBuffer getRequestURL() {
+                return new StringBuffer("http://localhost:8080/obr/" + m_requestFile);
+            }
+
+            @SuppressWarnings("unused")
+            public ServletInputStream getInputStream() {
+                return new ServletInputStream() {
+                    int i = 0;
+                    @Override
+                    public int read() throws IOException {
+                        if (i == 0) {
+                            i++;
+                            return 'a';
+                        }
+                        else {
+                            return -1;
+                        }
+                    }
+
+                };
+            }
+        });
+
+        // create a HttpServletResponse mock object
+        m_response = TestUtils.createMockObjectAdapter(HttpServletResponse.class, new Object() {
+            @SuppressWarnings("unused")
+            public ServletOutputStream getOutputStream() {
+                return new ServletOutputStream() {
+                    @Override
+                    public void write(int b) throws IOException {
+                        m_byteStream.write(b);
+                    }
+
+                    @Override
+                    public void println(String s) throws IOException {
+                        for (int i = 0; i < s.length(); i++) {
+                            m_byteStream.write(s.charAt(i));
+                        }
+                    }
+                };
+            }
+
+            @SuppressWarnings("unused")
+            public void sendError(int status) {
+                m_status = status;
+            }
+
+            @SuppressWarnings("unused")
+            public void sendError(int status, String description) {
+                m_status = status;
+            }
+        });
+        m_status = HttpServletResponse.SC_OK;
+    }
+
+    private File createRandomFileWithContent() throws IOException {
+        OutputStream fileOut = null;
+        File file = null;
+        try {
+            file = FileUtils.createTempFile(null);
+            fileOut = new FileOutputStream(file);
+            byte[] byteArray = new byte[12345];
+            Random randomContentCreator = new Random();
+            randomContentCreator.nextBytes(byteArray);
+            fileOut.write(byteArray);
+
+            return file;
+        }
+        finally {
+            try {
+                if (fileOut != null) {
+                    fileOut.close();
+                }
+            }
+            catch (IOException e) {
+                throw e;
+            }
+        }
+    }
+
+    @Test(groups = { UNIT })
+    public void testGetValidResource() throws Exception {
+        m_requestFile = m_testFile.getName();
+        m_bundleServlet.doGet(m_request, m_response);
+
+        assert m_status == HttpServletResponse.SC_OK : "We should have got response code " + HttpServletResponse.SC_OK + " and we got " + m_status;
+
+        boolean checkStream = checkOutputStreamForFile();
+        assert checkStream : "One stream stopped before the other one did.";
+    }
+
+    @Test(groups = { UNIT })
+    public void testGetInValidResource() throws Exception {
+        m_requestFile = "UnknownFile";
+        m_bundleServlet.doGet(m_request, m_response);
+
+        assert m_status == HttpServletResponse.SC_NOT_FOUND : "We should have got response code " + HttpServletResponse.SC_NOT_FOUND + " and we got " + m_status;
+    }
+
+    @Test(groups = { UNIT })
+    public void testPostResource() throws Exception {
+        m_requestFile = "NewFile";
+        m_bundleServlet.doPost(m_request, m_response);
+        assert m_status == HttpServletResponse.SC_OK;
+        m_requestFile = "ExistingFile";
+        m_bundleServlet.doPost(m_request, m_response);
+        assert m_status == HttpServletResponse.SC_CONFLICT;
+        m_requestFile = "";
+        m_bundleServlet.doPost(m_request, m_response);
+        assert m_status == HttpServletResponse.SC_BAD_REQUEST;
+    }
+
+    @Test(groups = { UNIT })
+    public void testRemoveResource() throws Exception {
+        m_requestFile = "RemoveMe";
+        m_bundleServlet.doDelete(m_request, m_response);
+        assert m_status == HttpServletResponse.SC_OK;
+        m_requestFile = "NonExistingFile";
+        m_bundleServlet.doDelete(m_request, m_response);
+        assert m_status == HttpServletResponse.SC_NOT_FOUND;
+    }
+
+    /**
+     * Check if the output from the server is the configured file
+     */
+    private boolean checkOutputStreamForFile() throws Exception {
+        assert m_testFile.length() == m_byteStream.size() : "Different filesize";
+
+        InputStream inStream = null;
+        InputStream outStream = null;
+        try {
+            // ok, the length is the same, now compare the content.
+            inStream = new BufferedInputStream(m_testFile.toURI().toURL().openStream());
+            outStream = new BufferedInputStream(new ByteArrayInputStream(m_byteStream.toByteArray()));
+            int inByte = inStream.read();
+            int outByte = outStream.read();
+            while ((inByte != -1) && (outByte != -1)) {
+                assert inByte == outByte : "Unexpected Stream content found";
+                inByte = inStream.read();
+                outByte = outStream.read();
+            }
+            return inByte == outByte;
+        }
+        finally {
+            try {
+                if (inStream != null) {
+                    inStream.close();
+                }
+            } finally {
+                if (outStream != null) {
+                    outStream.close();
+                }
+            }
+        }
+    }
+
+    @AfterMethod(alwaysRun = true)
+    protected void tearDown() {
+        m_byteStream = new ByteArrayOutputStream();
+        m_testFile.delete();
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/obr/servlet/MockBundleStore.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/obr/servlet/MockBundleStore.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/obr/servlet/MockBundleStore.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/obr/servlet/MockBundleStore.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,52 @@
+package net.luminis.liq.obr.servlet;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Dictionary;
+
+import net.luminis.liq.obr.storage.BundleStore;
+
+import org.osgi.service.cm.ConfigurationException;
+
+public class MockBundleStore implements BundleStore {
+
+    private InputStream m_outFile;
+
+    public MockBundleStore(InputStream outFile) {
+        m_outFile = outFile;
+    }
+
+    public InputStream get(String fileName) throws IOException {
+        if (fileName.equals("UnknownFile")) {
+            return null;
+        }
+        return m_outFile;
+    }
+
+    public void put(String fileName, OutputStream data) throws IOException {
+        // TODO does nothing yet
+    }
+
+    @Override
+    public boolean put(String fileName, InputStream data) throws IOException {
+        if (fileName.equals("NewFile")) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean remove(String fileName) throws IOException {
+        if (fileName.equals("RemoveMe")) {
+            return true;
+        }
+        return false;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void updated(Dictionary arg0) throws ConfigurationException {
+        // TODO does nothing yet
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/obr/storage/file/BundleFileStoreTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/obr/storage/file/BundleFileStoreTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/obr/storage/file/BundleFileStoreTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/obr/storage/file/BundleFileStoreTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,352 @@
+package net.luminis.liq.obr.storage.file;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Properties;
+import java.util.Random;
+
+import net.luminis.liq.obr.metadata.MetadataGenerator;
+import net.luminis.liq.obr.storage.BundleStore;
+import net.luminis.liq.obr.storage.file.constants.OBRFileStoreConstants;
+import net.luminis.liq.test.utils.FileUtils;
+import net.luminis.liq.test.utils.TestUtils;
+
+import org.osgi.service.cm.ConfigurationException;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class BundleFileStoreTest {
+
+    private BundleStore m_bundleStore;
+    private MockMetadataGenerator m_metadata;
+
+    private File m_directory;
+
+    private File m_bundleSubstitute1;
+    private File m_bundleSubstitute1Larger;
+    private File m_bundleSubstitute2;
+    private File m_bundleSubstitute3;
+    private File m_bundleRepositoryFile;
+
+    @BeforeMethod(alwaysRun = true)
+    protected void setUp() throws Exception {
+        m_bundleStore = new BundleFileStore();
+
+        m_directory = FileUtils.createTempFile(null);
+        m_directory.mkdir();
+
+        Properties props = new Properties();
+        props.put(OBRFileStoreConstants.FILE_LOCATION_KEY, m_directory.getAbsolutePath());
+        m_bundleStore.updated(props);
+
+        // create a mock MetadataGenerator
+        m_metadata = new MockMetadataGenerator();
+        TestUtils.configureObject(m_bundleStore, MetadataGenerator.class, m_metadata);
+
+        // create some bundles to work with
+        m_bundleSubstitute1 = createFileWithContent(m_directory.getAbsoluteFile(), "bundleSub1.jar", 1000);
+        m_bundleSubstitute2 = createFileWithContent(m_directory.getAbsoluteFile(), "bundleSub2.jar", 2000);
+        m_bundleSubstitute3 = createFileWithContent(m_directory.getAbsoluteFile(), "bundleSub3.jar", 3000);
+        m_bundleRepositoryFile = createFileWithContent(m_directory.getAbsoluteFile(), "repository.xml", 1000);
+    }
+
+    @AfterMethod(alwaysRun = true)
+    public void tearDown() throws Exception {
+        m_bundleSubstitute1.delete();
+        m_bundleSubstitute2.delete();
+        m_bundleSubstitute3.delete();
+        m_bundleRepositoryFile.delete();
+        m_directory.delete();
+    }
+
+    /**
+     * Test whether the metadata is generated when getting a bundle from the repository.
+     */
+    @Test(groups = { UNIT })
+    public void getBundle() throws Exception {
+        m_bundleStore.get(m_bundleSubstitute1.getName());
+        assert !m_metadata.generated() : "During getting a bundle, the metadata should not be regenerated.";
+    }
+
+    /**
+     * Test whether the metadata is generated when getting a bundle from the repository.
+     */
+    @Test(groups = { UNIT })
+    public void getUnexistingBundle() throws Exception {
+        try {
+            m_bundleStore.get("blaat");
+        }
+        catch (IOException e) {
+            // exception is expected
+            return;
+        }
+        assert false : "Getting an unexisting file did not result in an exception";
+    }
+
+    /**
+     * Test whether retrieving the repository.xml results in a call to the (mock) metadata generator,
+     * and the original file should correspond with the retrieved file.
+     */
+    @Test(groups = { UNIT })
+    public void getRepositoryFile() throws Exception {
+        InputStream newInputStream = m_bundleStore.get("repository.xml");
+        assert m_metadata.generated() : "During getting the repository file, the metadata should be regenerated.";
+
+        byte[] orgContentBuffer = new byte[1000];
+        newInputStream.read(orgContentBuffer);
+
+        FileInputStream orgInputStream = new FileInputStream(m_bundleRepositoryFile);
+        byte[] newContentBuffer = new byte[1000];
+        orgInputStream.read(newContentBuffer);
+
+        assert Arrays.equals(orgContentBuffer, newContentBuffer) : "The original repository.xml content should equal the newly retrieved content.";
+    }
+
+    /**
+     * Test whether the BundleStore notices the set of bundles has changed (bundle updated),
+     * and makes a call to the (mock) metadata generator.
+     */
+    @Test(groups = { UNIT })
+    public void updateBundle() throws Exception {
+        m_bundleStore.get("repository.xml");
+        assert m_metadata.numberOfCalls() == 1 : "The MetadataGenerator should be called once";
+
+        m_bundleSubstitute1Larger = createFileWithContent(m_directory.getAbsoluteFile(), "bundleSub1.jar", 2000);
+
+        m_bundleStore.get("repository.xml");
+        assert m_metadata.numberOfCalls() == 2 : "The MetadataGenerator should be called twice";
+
+        // test specific tear down
+        m_bundleSubstitute1Larger.delete();
+    }
+
+    /**
+     * Test whether the BundleStore notices the set of bundles has changed (bundle added),
+     * and makes a call to the (mock) metadata generator. Also a call should be made when
+     * a bundle is replaced by another one (number of bundles stay the same, but one bundle
+     * is replaced by another).
+     */
+    @Test(groups = { UNIT })
+    public void addBundle() throws Exception {
+        m_bundleStore.get("repository.xml");
+        assert m_metadata.numberOfCalls() == 1 : "The MetadataGenerator should be called once";
+
+        File bundleSubstituteX = createFileWithContent(m_directory.getAbsoluteFile(), "bundleSubX.jar", 2000);
+
+        m_bundleStore.get("repository.xml");
+        assert m_metadata.numberOfCalls() == 2 : "The MetadataGenerator should be called twice";
+
+        bundleSubstituteX.delete();
+
+        File bundleSubstituteY = createFileWithContent(m_directory.getAbsoluteFile(), "bundleSubY.jar", 2000);
+
+        m_bundleStore.get("repository.xml");
+        assert m_metadata.numberOfCalls() == 3 : "The MetadataGenerator should be called three times";
+
+        // test specific tear down
+        bundleSubstituteY.delete();
+    }
+
+    /**
+     * Test whether the BundleStore notices the set of bundles has not changed, and thus
+     * will not make a call to the (mock) metadata generator.
+     */
+    @Test(groups = { UNIT })
+    public void replaceWithSameBundle() throws Exception {
+        m_bundleStore.get("bundleSub1.jar");
+        assert m_metadata.numberOfCalls() == 0 : "The MetadataGenerator should not be called";
+
+        FileInputStream inputStream = new FileInputStream(m_bundleSubstitute1);
+        byte[] buffer = new byte[1000];
+        inputStream.read(buffer);
+        m_bundleSubstitute1.delete();
+
+        File newFile = new File(m_directory, "bundleSub1.jar");
+        FileOutputStream outputStream = new FileOutputStream(newFile);
+
+        outputStream.write(buffer);
+        outputStream.close();
+
+        m_bundleStore.get("bundleSub1.jar");
+        assert m_metadata.numberOfCalls() == 0 : "The MetadataGenerator should still not be called";
+    }
+
+    /**
+     * Test whether changing the directory where the bundles are stored, does not result in a call
+     * to the (mock) metadata generator, as the metadata will only be regenerated after getting
+     * a file.
+     */
+    @Test(groups = { UNIT })
+    public void updateConfigurationWithValidConfiguration() throws Exception {
+        File subDir = new File(m_directory.getAbsolutePath(), "changedDirectory");
+        subDir.mkdir();
+
+        Properties props = new Properties();
+        props.put(OBRFileStoreConstants.FILE_LOCATION_KEY, subDir.getAbsolutePath());
+        try {
+            m_bundleStore.updated(props);
+        }
+        catch (ConfigurationException e) {
+            assert false : "Reconfiguring directory failed, directory was '" + m_directory + "' but should be '" + subDir + "'";
+        }
+
+        assert !m_metadata.generated() : "After changing the directory, the metadata should not be regenerated.";
+
+        // test specific tear down
+        subDir.delete();
+    }
+
+    /**
+     * Test whether changing the directory where the bundles are stored to something that is not
+     * a directory, this should fail.
+     */
+    @Test(groups = { UNIT })
+    public void updateConfigurationWithIsNotDirectory() throws Exception {
+        boolean exceptionThrown = false;
+
+        File file = new File(m_directory.getAbsolutePath(), "file");
+        file.createNewFile();
+
+        Properties props = new Properties();
+        props.put(OBRFileStoreConstants.FILE_LOCATION_KEY, file.getAbsolutePath());
+        try {
+            m_bundleStore.updated(props);
+        }
+        catch (ConfigurationException e) {
+            // exception should be thrown as attempting to configure with File that is no directory
+            exceptionThrown = true;
+        }
+        assert exceptionThrown : "Reconfiguring directory succeeded, but should fail as it is no directory";
+
+        // test specific tear down
+        file.delete();
+    }
+
+    @Test(groups = { UNIT })
+    public void putBundle() throws Exception {
+        m_bundleStore.put("filename", new InputStream() {
+            private int i = 0;
+
+            @Override
+            public int read() throws IOException {
+                if (i < 1) {
+                    i++;
+                    return 'a';
+                }
+                else {
+                    return -1;
+                }
+            }
+        });
+        File file = new File(m_directory, "filename");
+        FileInputStream input = new FileInputStream(file);
+        assert input.read() == 'a';
+        assert input.read() == -1;
+        input.close();
+    }
+
+    @Test(groups = { UNIT })
+    public void removeExistingBundle() throws Exception {
+        m_bundleStore.put("filename", new InputStream() {
+            private int i = 0;
+
+            @Override
+            public int read() throws IOException {
+                if (i < 1) {
+                    i++;
+                    return 'a';
+                }
+                else {
+                    return -1;
+                }
+            }
+        });
+        File file = new File(m_directory, "filename");
+        assert file.exists();
+        m_bundleStore.remove("filename");
+        assert !file.exists();
+    }
+
+    /**
+     * Test whether not configuring the directory (so retrieving the directory returns null),
+     * results in a ConfigurationException. Updating with null as dictionary should only clean up
+     * things, and nothing else.
+     */
+    @Test(groups = { UNIT })
+    public void updateConfigurationWithNull() throws Exception {
+        boolean exceptionThrown = false;
+
+        Properties props = new Properties();
+        try {
+            m_bundleStore.updated(props);
+        }
+        catch (ConfigurationException e) {
+            exceptionThrown = true;
+        }
+        assert exceptionThrown : "Reconfiguring directory succeeded but should fail, as property is supposed to be missing";
+        assert !m_metadata.generated() : "After changing the directory, the metadata should not be regenerated.";
+
+
+        exceptionThrown = false;
+        try {
+            m_bundleStore.updated(null);
+        }
+        catch (ConfigurationException e) {
+            exceptionThrown = true;
+        }
+        assert !exceptionThrown : "Reconfiguring succeeded as the bundle should only do the clean up, and not throw exception";
+        assert !m_metadata.generated() : "After changing the directory, the metadata should not be regenerated.";
+    }
+
+    /**
+     * Test whether not configuring the directory (so retrieving the directory returns null),
+     * results in a ConfigurationException.
+     */
+    @Test(groups = { UNIT })
+    public void updateConfigurationWithSameDirectory() throws Exception {
+
+        Properties props = new Properties();
+        props.put(OBRFileStoreConstants.FILE_LOCATION_KEY, m_directory.getAbsolutePath());
+        try {
+            m_bundleStore.updated(props);
+        }
+        catch (ConfigurationException e) {
+            assert false : "Nothing should happen, as the directory did not change";
+        }
+        assert !m_metadata.generated() : "After changing the directory, the metadata should not be regenerated.";
+    }
+
+    private File createFileWithContent(File baseDir, String filename, int size) throws IOException {
+        OutputStream fileOut = null;
+        File file = new File(baseDir, filename);
+        try {
+            fileOut = new FileOutputStream(file);
+            byte[] byteArray = new byte[size];
+            Random randomContentCreator = new Random();
+            randomContentCreator.nextBytes(byteArray);
+            fileOut.write(byteArray);
+
+            return file;
+        }
+        finally {
+            try {
+                if (fileOut != null) {
+                    fileOut.close();
+                }
+            }
+            catch (IOException e) {
+                throw e;
+            }
+        }
+    }
+
+
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/obr/storage/file/MockMetadataGenerator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/obr/storage/file/MockMetadataGenerator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/obr/storage/file/MockMetadataGenerator.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/obr/storage/file/MockMetadataGenerator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,24 @@
+package net.luminis.liq.obr.storage.file;
+
+import java.io.File;
+
+import net.luminis.liq.obr.metadata.MetadataGenerator;
+
+public class MockMetadataGenerator implements MetadataGenerator{
+
+    private boolean m_generated = false;
+    private int m_numberOfCalls = 0;
+
+    public void generateMetadata(File metadataFilePath) {
+        m_numberOfCalls++;
+        m_generated = true;
+    }
+
+    public boolean generated() {
+        return m_generated;
+    }
+
+    public int numberOfCalls() {
+        return m_numberOfCalls;
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/repository/SortedRangeSetTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/repository/SortedRangeSetTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/repository/SortedRangeSetTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/repository/SortedRangeSetTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,57 @@
+package net.luminis.liq.repository;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import org.testng.annotations.Test;
+
+public class SortedRangeSetTest {
+    @Test(groups = { UNIT })
+    public void manipulateSimpleRanges() {
+        Range r1 = new Range("5");
+        assert r1.getLow() == 5 : "Lowest value should be 5";
+        assert r1.getHigh() == 5 : "Highest value should be 5";
+        assert r1.contains(5) : "Range should contain 5";
+        assert !r1.contains(4) : "Range should not contain 4";
+        assert !r1.contains(6) : "Range should not contain 6";
+        assert "5".equals(r1.toRepresentation()) : "Representation should be 5";
+        Range r2 = new Range("2-6");
+        assert r2.getLow() == 2 : "Lowest value should be 2";
+        assert r2.getHigh() == 6 : "Highest value should be 6";
+        assert r2.contains(6) : "Range should contain 6";
+        assert !r2.contains(7) : "Range should not contain 7";
+        assert !r2.contains(0) : "Range should not contain 0";
+        assert "2-6".equals(r2.toRepresentation()) : "Representation should be 2-6";
+        Range r3 = new Range(5);
+        assert r3.getLow() == 5 : "Lowest value should be 5";
+        assert r3.getHigh() == 5 : "Highest value should be 5";
+        Range r4 = new Range(6,8);
+        assert r4.getLow() == 6 : "Lowest value should be 6";
+        assert r4.getHigh() == 8 : "Highest value should be 8";
+        Range r5 = new Range(5);
+        r5.setLow(8);
+        assert r5.getHigh() == 8 : "Highest value should be 8";
+        r5.setHigh(2);
+        assert r5.getLow() == 2 : "Lowest value should be 2";
+    }
+
+    @Test(groups = { UNIT })
+    public void manipulateSortedRangeSets() {
+        SortedRangeSet s1 = new SortedRangeSet("1,3,5-8");
+        RangeIterator ri1 = s1.iterator();
+        assert ri1.next() == 1 : "Illegal value in range iterator";
+        assert ri1.next() == 3 : "Illegal value in range iterator";
+        assert ri1.next() == 5 : "Illegal value in range iterator";
+        assert ri1.next() == 6 : "Illegal value in range iterator";
+        assert ri1.next() == 7 : "Illegal value in range iterator";
+        assert ri1.next() == 8 : "Illegal value in range iterator";
+        assert !ri1.hasNext() : "There should not be more values in the iterator";
+        assert new SortedRangeSet("1-20").diffDest(new SortedRangeSet("5-25")).toRepresentation().equals("21-25") : "Result of diff should be 21-25";
+        assert new SortedRangeSet(new long[] {1,3,5,7,9}).diffDest(new SortedRangeSet("1-10")).toRepresentation().equals("2,4,6,8,10") : "Result of diff should be 2,4,6,8,10";
+        assert new SortedRangeSet("1-5,8,12").diffDest(new SortedRangeSet("1-5,7,9,12,20")).toRepresentation().equals("7,9,20") : "Result of diff should be 7,9,20";
+    }
+
+    @Test(groups = { UNIT }, expectedExceptions = IllegalArgumentException.class)
+    public void invalidRange() {
+        new SortedRangeSet("8-5");
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/repository/impl/RepositoryImplTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/repository/impl/RepositoryImplTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/repository/impl/RepositoryImplTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/repository/impl/RepositoryImplTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,114 @@
+package net.luminis.liq.repository.impl;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class RepositoryImplTest {
+
+    private RepositoryImpl m_repo;
+    private File m_baseDir;
+
+    @BeforeMethod(alwaysRun = true)
+    protected void setUp() throws IOException {
+        m_baseDir = File.createTempFile("repo", null);
+        m_baseDir.delete();
+        m_baseDir.mkdirs();
+        m_repo = new RepositoryImpl(new File(m_baseDir, "data"), new File(m_baseDir, "tmp"), true);
+    }
+
+    @Test(groups = { UNIT })
+    public void testGetAndPut() throws Exception {
+        InputStream data = new ByteArrayInputStream("abc".getBytes());
+        boolean result = m_repo.put(data, 1);
+        assert result : "Put should have succeeded.";
+
+        File file = new File(m_baseDir, "data" + File.separator + "1");
+        BufferedReader reader = new BufferedReader(new FileReader(file));
+        assert "abc".equals(reader.readLine()) : "File " + file.getAbsolutePath() + " should have contained 'abc'.";
+
+        assert !m_repo.put(data, 1) : "Putting an existing version should return false.";
+
+        InputStream in = m_repo.get(1);
+        reader = new BufferedReader(new InputStreamReader(in));
+        assert "abc".equals(reader.readLine()) : "'get'ting version 1 should have returned an inputstream containing 'abc'";
+        assert null == m_repo.get(2) : "'get'ting a non-existing version should return null";
+    }
+
+    @Test(groups = { UNIT }, expectedExceptions = {IllegalArgumentException.class})
+    public void testPutNegative() throws Exception {
+        m_repo.put(new ByteArrayInputStream("abc".getBytes()), -1);
+    }
+
+    @Test(groups = { UNIT }, expectedExceptions = {IllegalArgumentException.class})
+    public void testPutZero() throws Exception {
+        m_repo.put(new ByteArrayInputStream("abc".getBytes()), 0);
+    }
+
+    @Test(groups = { UNIT }, expectedExceptions = {IllegalArgumentException.class})
+    public void testGetNegative() throws Exception {
+        m_repo.get(-1);
+    }
+
+    @Test(groups = { UNIT }, expectedExceptions = {IllegalArgumentException.class})
+    public void testGetZero() throws Exception {
+        m_repo.get(0);
+    }
+
+    @Test(groups = { UNIT })
+    public void testCommitAndCheckout() throws Exception {
+        InputStream data = new ByteArrayInputStream("abc".getBytes());
+        boolean result = m_repo.commit(data, 1);
+        assert !result : "Commit with incorrect 'base' number should have failed.";
+
+        result = m_repo.commit(data, 0);
+        assert result : "Commit should have succeeded";
+
+        File file = new File(m_baseDir, "data" + File.separator + "1");
+        BufferedReader reader = new BufferedReader(new FileReader(file));
+        assert "abc".equals(reader.readLine()) : "File " + file.getAbsolutePath() + " should have contained 'abc'.";
+
+        assert !m_repo.commit(data, 0) : "Committing an existing version should return false.";
+        assert !m_repo.commit(data, 999) : "Committing should only succeed if the base number equals the highest version inside the repository";
+
+        InputStream in = m_repo.checkout(1);
+        reader = new BufferedReader(new InputStreamReader(in));
+        assert "abc".equals(reader.readLine()) : "Checking out version 1 should have returned an inputstream containing 'abc'";
+        assert null == m_repo.get(2) : "Checking out a non-existing version should return null";
+    }
+
+    @Test(groups = { UNIT }, expectedExceptions = {IllegalArgumentException.class})
+    public void testCommitNegative() throws Exception {
+        m_repo.commit(new ByteArrayInputStream("abc".getBytes()), -1);
+    }
+
+    @Test(groups = { UNIT }, expectedExceptions = {IllegalArgumentException.class})
+    public void testCheckoutNegative() throws Exception {
+        m_repo.checkout(-1);
+    }
+
+    @Test(groups = { UNIT }, expectedExceptions = {IllegalArgumentException.class})
+    public void testCheckoutZero() throws Exception {
+        m_repo.checkout(0);
+    }
+
+    @Test(groups = { UNIT }, expectedExceptions = {IllegalStateException.class})
+    public void testUpdated() throws Exception {
+        m_repo.updated(false);
+        assert !m_repo.commit(new ByteArrayInputStream("abc".getBytes()), 0) : "Committing should not be allowed on slave repositories.";
+        assert m_repo.put(new ByteArrayInputStream("abc".getBytes()), 1) : "'put'ting a replica should be allowed on slave repositories.";
+        File file = new File(m_baseDir, "newLocation" + File.separator + "1");
+        BufferedReader reader = new BufferedReader(new FileReader(file));
+        assert "abc".equals(reader.readLine()) : "File " + file.getAbsolutePath() + " should have contained 'abc'.";
+    }
+
+}
\ No newline at end of file

Added: incubator/ace/trunk/test/src/net/luminis/liq/scheduler/ExecuterTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/scheduler/ExecuterTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/scheduler/ExecuterTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/scheduler/ExecuterTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,56 @@
+package net.luminis.liq.scheduler;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+
+public class ExecuterTest {
+
+    private Semaphore m_sem;
+
+    @BeforeMethod(groups = { UNIT })
+    public void setup() {
+    }
+
+    /* start task, verify if it has run */
+    @Test(groups = { UNIT })
+    public void testExecute() throws Exception {
+        m_sem = new Semaphore(1);
+        Executer executer = new Executer(new Runnable() {
+            @Override
+            public void run() {
+                m_sem.release();
+            }
+        });
+        executer.start(100);
+        m_sem.acquire();
+        assert m_sem.tryAcquire(2, TimeUnit.SECONDS);
+    }
+
+    /* start task, stop it, verify if it executed only once */
+    @Test(groups = { UNIT })
+    public void testStop() throws Exception {
+        m_sem = new Semaphore(2);
+        Executer executer = new Executer(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    m_sem.tryAcquire(1, TimeUnit.SECONDS);
+                }
+                catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+        executer.start(10);
+        executer.stop();
+        Thread.sleep(100);
+        assert m_sem.tryAcquire(1, TimeUnit.SECONDS);
+    }
+
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/scheduler/SchedulerTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/scheduler/SchedulerTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/scheduler/SchedulerTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/scheduler/SchedulerTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,129 @@
+package net.luminis.liq.scheduler;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.util.Properties;
+
+import net.luminis.liq.test.utils.TestUtils;
+
+import org.osgi.service.cm.ConfigurationException;
+import org.osgi.service.log.LogService;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class SchedulerTest {
+
+    private Scheduler m_scheduler;
+
+    @BeforeMethod(alwaysRun = true)
+    protected void setUp() throws Exception {
+        m_scheduler = new Scheduler();
+        TestUtils.configureObject(m_scheduler, LogService.class);
+    }
+
+    @Test(groups = { UNIT }, expectedExceptions = IllegalArgumentException.class)
+    public synchronized void testIllegalCreation() {
+        new SchedulerTask(null);
+    }
+
+    @Test(groups = { UNIT })
+    public synchronized void testUpdate() throws Exception {
+        Properties props = new Properties();
+        props.put("local.mock.task1", 1000l);
+        props.put("local.mock.task2", 2000l);
+        props.put("local.mock.task3", 3000l);
+        m_scheduler.updated(props);
+        assert m_scheduler.m_tasks.size() == props.size() : "Exactly three schedules should be known to the scheduler";
+        assert ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).getCurrentRecipe().equals(new Long(1000)) : "The schedule for mock task 1 should specify interval 1000, but it specifies " + ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).getCurrentRecipe();
+
+        props.put("local.mock.task1", 4000l);
+        m_scheduler.updated(props);
+        assert ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).getCurrentRecipe().equals(new Long(4000)) : "The schedule for mock task 1 should specify interval 4000, but it specifies " + ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).getCurrentRecipe();
+        assert !((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).isScheduled() : "Since we have not provided a runnable for the scheduler, the tasks should not be scheduled.";
+    }
+
+    @Test(groups = { UNIT }, expectedExceptions = ConfigurationException.class)
+    public synchronized void testIllegalUpdate() throws Exception {
+        Properties props = new Properties();
+        props.put("local.mock.task1", "invalidValue");
+        m_scheduler.updated(props);
+        m_scheduler.addRunnable("local.mock.task1", new Runnable() {
+            @Override
+            public void run() {
+            }}, "Dummy testing task", null, false);
+    }
+
+    @Test(groups = { UNIT })
+    public synchronized void testAddTask() throws Exception {
+        assert m_scheduler.m_tasks.isEmpty();
+        m_scheduler.addRunnable("local.mock.task1", new Runnable() {
+            @Override
+            public void run() {
+            }}, "Dummy testing task", null, false);
+        assert m_scheduler.m_tasks.size() == 1 : "Exactly one task should be known to the scheduler";
+        SchedulerTask task = (SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1");
+        assert "local.mock.task1".equals(task.getName()) : "Task that was just added has a different name than expected";
+    }
+
+    @Test(groups = { UNIT })
+    public synchronized void testRemoveTask() throws Exception {
+        m_scheduler.addRunnable("local.mock.task1", new Runnable() {
+            @Override
+            public void run() {
+            }}, "Dummy testing task", null, false);
+        m_scheduler.removeRunnable("nonExistent");
+        assert m_scheduler.m_tasks.size() == 1 : "Number of tasks known to the scheduler should still be one after removing a non-existing task";
+        m_scheduler.removeRunnable("local.mock.task1");
+        assert m_scheduler.m_tasks.isEmpty() : "Number of tasks known to the scheduler should be zero after removing the task we just added";
+    }
+
+    @Test(groups = { UNIT })
+    public synchronized void testProcessTask() throws Exception {
+        Properties props = new Properties();
+        props.put("local.mock.task1", 1000);
+        m_scheduler.updated(props);
+
+        m_scheduler.addRunnable("local.mock.task1", new Runnable() {
+            @Override
+            public void run() {
+            }}, "Dummy testing task", null, false);
+
+        assert ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).isScheduled() : "An executer should exist after adding a matching task and scheduling-recipe";
+    }
+
+    @Test(groups = { UNIT })
+    public synchronized void testSchedulePrevailanceAndRemoval() throws Exception {
+        Properties props = new Properties();
+        props.put("local.mock.task1", 1000l);
+        m_scheduler.updated(props);
+
+        assert ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).getCurrentRecipe().equals(new Long(1000)) : "The schedule for mock task 1 should specify interval 1000, but it specifies " + ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).getCurrentRecipe();
+        assert !((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).isScheduled() : "Since we have not provided a runnable for the scheduler, the tasks should not be scheduled.";
+
+        m_scheduler.addRunnable("local.mock.task1", new Runnable() {
+            @Override
+            public void run() {
+            }}, "Dummy testing task", 2000l, true);
+
+        assert ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).getCurrentRecipe().equals(new Long(2000)) : "The schedule for mock task 1 should specify interval 2000, but it specifies " + ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).getCurrentRecipe();
+        assert ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).isScheduled() : "Since we have now provided a runnable for the scheduler, the tasks should be scheduled.";
+
+        m_scheduler.addRunnable("local.mock.task1", new Runnable() {
+            @Override
+            public void run() {
+            }}, "Dummy testing task", 2000l, false);
+
+        assert ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).getCurrentRecipe().equals(new Long(1000)) : "The schedule for mock task 1 should specify interval 1000, but it specifies " + ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).getCurrentRecipe();
+        assert ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).isScheduled() : "Since we have now provided a runnable for the scheduler, the tasks should be scheduled.";
+
+        props = new Properties();
+        m_scheduler.updated(props);
+
+        assert ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).getCurrentRecipe().equals(new Long(2000)) : "The schedule for mock task 1 should specify interval 2000, but it specifies " + ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).getCurrentRecipe();
+        assert ((SchedulerTask) m_scheduler.m_tasks.get("local.mock.task1")).isScheduled() : "Since we have now provided a runnable for the scheduler, the tasks should be scheduled.";
+
+        m_scheduler.removeRunnable("local.mock.task1");
+
+        assert m_scheduler.m_tasks.size() == 0 : "We have now removed all information about mock task 1, so it should be gone now.";
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/server/log/LogServletTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/server/log/LogServletTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/server/log/LogServletTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/server/log/LogServletTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,148 @@
+package net.luminis.liq.server.log;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+
+import net.luminis.liq.log.LogDescriptor;
+import net.luminis.liq.log.LogEvent;
+import net.luminis.liq.repository.SortedRangeSet;
+import net.luminis.liq.server.log.store.LogStore;
+import net.luminis.liq.test.utils.TestUtils;
+
+import org.osgi.service.log.LogService;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class LogServletTest {
+
+    private LogServlet m_logServlet;
+    private LogDescriptor m_range = new LogDescriptor("gwID", 123, new SortedRangeSet("1-3"));
+    private LogEvent m_event1 = new LogEvent("gwID", 123, 1, 888888, 1, new Properties());
+    private LogEvent m_event2 = new LogEvent("gwID", 123, 2, 888888, 2, new Properties());
+    private MockLogStore m_mockStore;
+
+    @BeforeMethod(alwaysRun = true)
+    protected void setUp() throws Exception {
+        m_logServlet = new LogServlet("test");
+        TestUtils.configureObject(m_logServlet, LogService.class);
+        m_mockStore = new MockLogStore();
+        TestUtils.configureObject(m_logServlet, LogStore.class, m_mockStore);
+    }
+
+    @AfterMethod(alwaysRun = true)
+    protected void tearDown() throws Exception {
+    }
+
+    @Test(groups = { UNIT })
+    public void queryLog() throws Exception {
+        MockServletOutputStream output = new MockServletOutputStream();
+        boolean result = m_logServlet.handleQuery(m_range.getGatewayID(), String.valueOf(m_range.getLogID()), null, output);
+        assert result;
+        assert m_range.toRepresentation().equals(output.m_text);
+        output.m_text = "";
+        result = m_logServlet.handleQuery(null, null, null, output);
+        assert result;
+        assert (m_range.toRepresentation() + "\n").equals(output.m_text);
+    }
+
+    @Test(groups = { UNIT })
+    public void receiveLog() throws Exception {
+        MockServletOutputStream output = new MockServletOutputStream();
+        boolean result = m_logServlet.handleReceive(m_range.getGatewayID(), String.valueOf(m_range.getLogID()), "1", null, output);
+        assert result;
+        String expected = m_event1.toRepresentation() + "\n";
+        String actual = output.m_text;
+        assert expected.equals(actual) : "We expected '" + expected + "', but received '" + actual + "'";
+
+        output = new MockServletOutputStream();
+        result = m_logServlet.handleReceive(m_range.getGatewayID(), String.valueOf(m_range.getLogID()), null , null, output);
+        assert result;
+        expected = m_event1.toRepresentation() + "\n" + m_event2.toRepresentation() + "\n";
+        actual = output.m_text;
+        assert expected.equals(actual) : "We expected '" + expected + "', but received '" + actual + "'";;
+    }
+
+    @Test(groups = { UNIT })
+    public void sendLog() throws Exception {
+        MockServletInputStream input = new MockServletInputStream();
+        String expected = m_event1.toRepresentation() + "\n" + m_event2.toRepresentation() + "\n";
+        input.setBytes(expected.getBytes());
+        m_logServlet.handleSend(input);
+
+        String actual = "";
+        for (Iterator<LogEvent> i = m_mockStore.m_events.iterator(); i.hasNext();) {
+            LogEvent event = i.next();
+            actual = actual + event.toRepresentation() + "\n";
+        }
+        assert expected.equals(actual);
+    }
+
+    private class MockLogStore implements LogStore {
+        public List<LogEvent> m_events = new ArrayList<LogEvent>();
+
+        public List<LogEvent> get(LogDescriptor range) {
+            List<LogEvent> events = new ArrayList<LogEvent>();
+            if (range.getRangeSet().contains(1)) {
+                events.add(m_event1);
+            }
+            if (range.getRangeSet().contains(2)) {
+                events.add(m_event2);
+            }
+            return events;
+        }
+        public List<LogDescriptor> getDescriptors(String gatewayID) {
+            return null;
+        }
+        public List<LogDescriptor> getDescriptors() {
+            List<LogDescriptor> ranges = new ArrayList<LogDescriptor>();
+            ranges.add(m_range);
+            return ranges;
+        }
+        public LogDescriptor getDescriptor(String gatewayID, long logID) throws IOException {
+            return m_range;
+        }
+        public void put(List<LogEvent> events) throws IOException {
+            m_events = events;
+        }
+    }
+
+    private class MockServletOutputStream extends ServletOutputStream {
+        public String m_text = "";
+
+        @Override
+        public void print(String s) throws IOException {
+            m_text = m_text.concat(s);
+        }
+        @Override
+        public void write(int arg0) throws IOException {
+        }
+    }
+
+    private class MockServletInputStream extends ServletInputStream {
+        private int i = 0;
+        private byte[] m_bytes;
+
+        @Override
+        public int read() throws IOException {
+            int result = -1;
+            if (i < m_bytes.length) {
+                result = m_bytes[i];
+                i++;
+            }
+            return result;
+        }
+
+        public void setBytes(byte[] bytes) {
+            m_bytes = bytes;
+        }
+    }
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/server/log/store/impl/ServerLogStoreTester.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/server/log/store/impl/ServerLogStoreTester.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/server/log/store/impl/ServerLogStoreTester.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/server/log/store/impl/ServerLogStoreTester.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,102 @@
+package net.luminis.liq.server.log.store.impl;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+import net.luminis.liq.log.AuditEvent;
+import net.luminis.liq.log.LogDescriptor;
+import net.luminis.liq.log.LogEvent;
+import net.luminis.liq.test.utils.TestUtils;
+
+import org.osgi.service.event.EventAdmin;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+public class ServerLogStoreTester {
+    private LogStoreImpl m_logStore;
+    private File m_dir;
+
+    @BeforeMethod(alwaysRun = true)
+    protected void setUp() throws Exception {
+        m_dir = File.createTempFile("logstore", "txt");
+        m_dir.delete();
+        m_dir.mkdirs();
+        m_logStore = new LogStoreImpl(m_dir, "log");
+        TestUtils.configureObject(m_logStore, EventAdmin.class);
+        m_logStore.start();
+    }
+
+    @AfterMethod(alwaysRun = true)
+    protected void tearDown() throws IOException {
+        delete(m_dir);
+    }
+
+    @SuppressWarnings("serial")
+    @Test(groups = { UNIT })
+    public void testLog() throws IOException {
+        List<LogDescriptor> ranges = m_logStore.getDescriptors();
+        assert ranges.isEmpty() : "New store should have no ranges.";
+        List<LogEvent> events = new ArrayList<LogEvent>();
+        for (String gateway : new String[] { "g1", "g2", "g3" }) {
+            for (long log : new long[] { 1, 2, 3, 5 }) {
+                for (long id : new long[] { 1, 2, 3, 20 }) {
+                    events.add(new LogEvent(gateway, log, id, System.currentTimeMillis(), AuditEvent.FRAMEWORK_STARTED, new Properties() {
+                        {
+                            put("test", "bar");
+                        }
+                    }));
+                }
+            }
+        }
+        m_logStore.put(events);
+        assert m_logStore.getDescriptors().size() == 3 * 4 : "Incorrect amount of ranges returned from store";
+        List<LogEvent> stored = new ArrayList<LogEvent>();
+        for (LogDescriptor range : m_logStore.getDescriptors()) {
+            for (LogDescriptor range2 : m_logStore.getDescriptors(range.getGatewayID())) {
+                stored.addAll(m_logStore.get(m_logStore.getDescriptor(range2.getGatewayID(), range2.getLogID())));
+            }
+        }
+
+        Set<String> in = new HashSet<String>();
+        for (LogEvent event : events)  {
+            in.add(event.toRepresentation());
+        }
+        Set<String> out = new HashSet<String>();
+        for (LogEvent event : stored) {
+            out.add(event.toRepresentation());
+        }
+        assert in.equals(out) : "Stored events differ from the added.";
+    }
+
+    /**
+     * See ATL-1537
+     */
+    @Test( groups = { TestUtils.UNIT } )
+    public void testLogWithSpecialCharacters() throws IOException {
+        String gatewayID = "myga\0teway";
+        LogEvent event = new LogEvent(gatewayID, 1, 1, System.currentTimeMillis(), AuditEvent.FRAMEWORK_STARTED, new Properties());
+        List<LogEvent> events = new ArrayList<LogEvent>();
+        events.add(event);
+        m_logStore.put(events);
+        assert m_logStore.getDescriptors().size() == 1 : "Incorrect amount of ranges returned from store: expected 1, found " + m_logStore.getDescriptors().size();
+        assert m_logStore.getDescriptors(gatewayID).size() == 1 : "We expect to find a single event: expected 1, found " + m_logStore.getDescriptors(gatewayID).size();
+    }
+
+    private void delete(File root) {
+        if (root.isDirectory()) {
+            for (File child : root.listFiles()) {
+                delete(child);
+            }
+        }
+        root.delete();
+    }
+
+}

Added: incubator/ace/trunk/test/src/net/luminis/liq/server/log/task/LogTaskTest.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/test/src/net/luminis/liq/server/log/task/LogTaskTest.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/test/src/net/luminis/liq/server/log/task/LogTaskTest.java (added)
+++ incubator/ace/trunk/test/src/net/luminis/liq/server/log/task/LogTaskTest.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,89 @@
+package net.luminis.liq.server.log.task;
+
+import static net.luminis.liq.test.utils.TestUtils.UNIT;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.List;
+
+import net.luminis.liq.log.LogDescriptor;
+import net.luminis.liq.repository.RangeIterator;
+import net.luminis.liq.repository.SortedRangeSet;
+
+import org.testng.annotations.Test;
+
+public class LogTaskTest {
+
+    private class MockLogSyncTask extends LogSyncTask {
+        public List<LogDescriptor> m_calledWith = new ArrayList<LogDescriptor>();
+
+        public MockLogSyncTask(String endpoint, String name) {
+            super(endpoint, name);
+        }
+
+        @Override
+        protected void writeLogDescriptor(LogDescriptor descriptor, Writer writer) throws IOException {
+            m_calledWith.add(descriptor);
+        }
+
+    }
+
+    /**
+     * This test tests both delta computation and push behavior.
+     */
+    @Test(groups = { UNIT })
+    public void testDeltaComputation() throws IOException {
+        // TODO: Test the new LogDescriptor.
+        List<LogDescriptor> src = new ArrayList<LogDescriptor>();
+        List<LogDescriptor> dest = new ArrayList<LogDescriptor>();
+        MockLogSyncTask task = new MockLogSyncTask("mocklog", "mocklog");
+        // compare two empty lists
+        task.writeDelta(task.calculateDelta(src, dest), null);
+        assert task.m_calledWith.isEmpty() : "Delta of two empty lists should be empty";
+        // add something to the source
+        src.add(new LogDescriptor("gwid", 1, new SortedRangeSet("1-5")));
+        task.writeDelta(task.calculateDelta(src, dest), null);
+        assert task.m_calledWith.size() == 1 : "Delta should be 1 instead of: " + task.m_calledWith.size();
+        task.m_calledWith.clear();
+        // add an overlapping destination
+        dest.add(new LogDescriptor("gwid", 1, new SortedRangeSet("1-3")));
+        task.writeDelta(task.calculateDelta(src, dest), null);
+        assert task.m_calledWith.size() == 1 : "Delta should be 1 instead of: " + task.m_calledWith.size();
+        RangeIterator i = task.m_calledWith.get(0).getRangeSet().iterator();
+        assert i.next() == 4 : "Illegal value in SortedRangeSet";
+        assert i.next() == 5 : "Illegal value in SortedRangeSet";
+        assert !i.hasNext() : "Illegal value in SortedRangeSet";
+        task.m_calledWith.clear();
+        // add a non-overlapping destination
+        dest.add(new LogDescriptor("gwid", 2, new SortedRangeSet("50-100")));
+        task.writeDelta(task.calculateDelta(src, dest), null);
+        assert task.m_calledWith.size() == 1 : "Delta should be 1 instead of: " + task.m_calledWith.size();
+        i = task.m_calledWith.get(0).getRangeSet().iterator();
+        assert i.next() == 4 : "Illegal value in SortedRangeSet";
+        assert i.next() == 5 : "Illegal value in SortedRangeSet";
+        assert !i.hasNext() : "Illegal value in SortedRangeSet";
+        task.m_calledWith.clear();
+        // add non-overlapping source
+        src.add(new LogDescriptor("gwid", 2, new SortedRangeSet("1-49")));
+        task.writeDelta(task.calculateDelta(src, dest), null);
+        assert task.m_calledWith.size() == 2 : "Delta should be 2 instead of: " + task.m_calledWith.size();
+        task.m_calledWith.clear();
+        // add a source with gaps
+        src.add(new LogDescriptor("gwid", 3, new SortedRangeSet("1-10")));
+        dest.add(new LogDescriptor("gwid", 3, new SortedRangeSet("3,5-8")));
+        task.writeDelta(task.calculateDelta(src, dest), null);
+        assert task.m_calledWith.size() == 3 : "Delta should be 3 instead of: " + task.m_calledWith.size();
+        for (LogDescriptor l : task.m_calledWith) {
+            if (l.getLogID() == 3) {
+                i = l.getRangeSet().iterator();
+            }
+        }
+        assert i.next() == 1 : "Illegal value in SortedRangeSet";
+        assert i.next() == 2 : "Illegal value in SortedRangeSet";
+        assert i.next() == 4 : "Illegal value in SortedRangeSet";
+        assert i.next() == 9 : "Illegal value in SortedRangeSet";
+        assert i.next() == 10 : "Illegal value in SortedRangeSet";
+        assert !i.hasNext() : "Illegal value in SortedRangeSet";
+    }
+}