changeset 135:1c81ec720fc7

Refactor CpuStat use in client to use DAO reviewed-by: omajid, rkennke review-thread: http://icedtea.classpath.org/pipermail/thermostat/2012-March/000388.html
author Jon VanAlten <jon.vanalten@redhat.com>
date Thu, 22 Mar 2012 11:59:20 -0400
parents 6cddcff70160
children 5c979486c4e6
files client/src/main/java/com/redhat/thermostat/client/HostPanelFacadeImpl.java client/src/main/java/com/redhat/thermostat/client/ui/HostCpuController.java client/src/main/java/com/redhat/thermostat/client/ui/HostMemoryController.java client/src/test/java/com/redhat/thermostat/client/VmClassStatControllerTest.java client/src/test/java/com/redhat/thermostat/client/ui/CpuStatControllerTest.java common/src/main/java/com/redhat/thermostat/common/dao/CpuStatConverter.java common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAO.java common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAO.java common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAO.java common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAOImpl.java common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAO.java common/src/main/java/com/redhat/thermostat/common/storage/Key.java common/src/test/java/com/redhat/thermostat/common/dao/CpuStatConverterTest.java common/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java common/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java
diffstat 19 files changed, 356 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/client/src/main/java/com/redhat/thermostat/client/HostPanelFacadeImpl.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/client/src/main/java/com/redhat/thermostat/client/HostPanelFacadeImpl.java	Thu Mar 22 11:59:20 2012 -0400
@@ -51,7 +51,7 @@
 
     public HostPanelFacadeImpl(HostRef ref, DB db) {
         overviewController = new HostOverviewController(ref, db);
-        cpuController = new HostCpuController(ref, db);
+        cpuController = new HostCpuController(ref);
         memoryController = new HostMemoryController(ref, db);
     }
 
--- a/client/src/main/java/com/redhat/thermostat/client/ui/HostCpuController.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/HostCpuController.java	Thu Mar 22 11:59:20 2012 -0400
@@ -43,40 +43,30 @@
 import java.util.TimerTask;
 import java.util.concurrent.TimeUnit;
 
-import com.mongodb.BasicDBObject;
-import com.mongodb.DB;
-import com.mongodb.DBCollection;
-import com.mongodb.DBCursor;
-import com.mongodb.DBObject;
 import com.redhat.thermostat.client.AsyncUiFacade;
 import com.redhat.thermostat.client.DiscreteTimeData;
 import com.redhat.thermostat.client.appctx.ApplicationContext;
 import com.redhat.thermostat.common.CpuStat;
 import com.redhat.thermostat.common.HostInfo;
-import com.redhat.thermostat.common.dao.CpuStatConverter;
+import com.redhat.thermostat.common.dao.CpuStatDAO;
+import com.redhat.thermostat.common.dao.DAOFactory;
 import com.redhat.thermostat.common.dao.HostInfoDAO;
 import com.redhat.thermostat.common.dao.HostRef;
 
 public class HostCpuController implements AsyncUiFacade {
 
-    private final HostRef hostRef;
-
     private final HostCpuView view;
     private final Timer backgroundUpdateTimer = new Timer();
 
     private final HostInfoDAO hostInfoDAO;
-    private final DBCollection cpuStatsCollection;
-
-    private long cpuLoadLastUpdateTime = Long.MIN_VALUE;
+    private final CpuStatDAO cpuStatDAO;
 
-    public HostCpuController(HostRef ref, DB db) {
-        hostRef = ref;
-
+    public HostCpuController(HostRef ref) {
         view = createView();
         view.clearCpuLoadData();
-
-        cpuStatsCollection = db.getCollection("cpu-stats");
-        hostInfoDAO = ApplicationContext.getInstance().getDAOFactory().getHostInfoDAO(ref);
+        DAOFactory daos = ApplicationContext.getInstance().getDAOFactory();
+        hostInfoDAO = daos.getHostInfoDAO(ref);
+        cpuStatDAO = daos.getCpuStatDAO(ref);
     }
 
     @Override
@@ -88,7 +78,7 @@
                 HostInfo hostInfo = hostInfoDAO.getHostInfo();
 
                 view.setCpuCount(String.valueOf(hostInfo.getCpuCount()));
-                view.setCpuModel(String.valueOf(hostInfo.getCpuModel()));
+                view.setCpuModel(hostInfo.getCpuModel());
 
                 doCpuChartUpdate();
             }
@@ -101,20 +91,11 @@
     }
 
     private void doCpuChartUpdate() {
-
-        BasicDBObject query = new BasicDBObject();
-        query.put("agent-id", this.hostRef.getAgentId());
-        query.put("timestamp", new BasicDBObject("$gt", cpuLoadLastUpdateTime));
-
-        DBCursor cursor = cpuStatsCollection.find(query);
-
+        List<CpuStat> cpuStats = cpuStatDAO.getLatestCpuStats();
         List<DiscreteTimeData<Double>> result = new ArrayList<DiscreteTimeData<Double>>();
-        for (DBObject dbObj: cursor) {
-                CpuStat stat = new CpuStatConverter().fromDB(dbObj);
-                cpuLoadLastUpdateTime = Math.max(cpuLoadLastUpdateTime, stat.getTimeStamp());
-                result.add(new DiscreteTimeData<Double>(stat.getTimeStamp(), stat.getLoad5()));
+        for (CpuStat stat : cpuStats) {
+            result.add(new DiscreteTimeData<Double>(stat.getTimeStamp(), stat.getLoad5()));
         }
-
         view.addCpuLoadData(result);
     }
 
--- a/client/src/main/java/com/redhat/thermostat/client/ui/HostMemoryController.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/client/src/main/java/com/redhat/thermostat/client/ui/HostMemoryController.java	Thu Mar 22 11:59:20 2012 -0400
@@ -59,7 +59,6 @@
 import com.redhat.thermostat.client.ui.HostMemoryView.GraphVisibilityChangeListener;
 import com.redhat.thermostat.common.HostInfo;
 import com.redhat.thermostat.common.MemoryStat;
-import com.redhat.thermostat.common.dao.HostInfoConverter;
 import com.redhat.thermostat.common.dao.HostInfoDAO;
 import com.redhat.thermostat.common.dao.HostRef;
 import com.redhat.thermostat.common.dao.MemoryStatConverter;
--- a/client/src/test/java/com/redhat/thermostat/client/VmClassStatControllerTest.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/client/src/test/java/com/redhat/thermostat/client/VmClassStatControllerTest.java	Thu Mar 22 11:59:20 2012 -0400
@@ -53,7 +53,7 @@
 import com.redhat.thermostat.common.VmClassStat;
 import com.redhat.thermostat.common.dao.DAOFactory;
 import com.redhat.thermostat.common.dao.MongoDAOFactory;
-import com.redhat.thermostat.common.dao.VmClassStatDAOImpl;
+import com.redhat.thermostat.common.dao.VmClassStatDAO;
 import com.redhat.thermostat.common.dao.VmRef;
 
 public class VmClassStatControllerTest {
@@ -65,7 +65,7 @@
         List<VmClassStat> stats = new ArrayList<VmClassStat>();
         stats.add(stat1);
 
-        VmClassStatDAOImpl vmClassStatDAO = mock(VmClassStatDAOImpl.class);
+        VmClassStatDAO vmClassStatDAO = mock(VmClassStatDAO.class);
         when(vmClassStatDAO.getLatestClassStats()).thenReturn(stats).thenReturn(new ArrayList<VmClassStat>());
 
         DAOFactory daoFactory = mock(MongoDAOFactory.class);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/client/src/test/java/com/redhat/thermostat/client/ui/CpuStatControllerTest.java	Thu Mar 22 11:59:20 2012 -0400
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.client.ui;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import com.redhat.thermostat.client.appctx.ApplicationContext;
+import com.redhat.thermostat.common.CpuStat;
+import com.redhat.thermostat.common.HostInfo;
+import com.redhat.thermostat.common.dao.CpuStatDAO;
+import com.redhat.thermostat.common.dao.DAOFactory;
+import com.redhat.thermostat.common.dao.HostInfoDAO;
+import com.redhat.thermostat.common.dao.HostRef;
+import com.redhat.thermostat.common.dao.MongoDAOFactory;
+
+public class CpuStatControllerTest {
+
+    @Test
+    public void testUpdate() {
+
+        CpuStat stat = new CpuStat(10L, 5.0, 10.0, 15.0);
+        List<CpuStat> stats = new ArrayList<CpuStat>();
+        stats.add(stat);
+
+        CpuStatDAO cpuStatDAO = mock(CpuStatDAO.class);
+        when(cpuStatDAO.getLatestCpuStats()).thenReturn(stats).thenReturn(new ArrayList<CpuStat>());
+
+        HostInfo hostInfo = new HostInfo("someHost", "someOS", "linux_0.0.1", "lreally_fast_cpu", 2, 1024);
+        HostInfoDAO hostInfoDAO = mock(HostInfoDAO.class);
+        when(hostInfoDAO.getHostInfo()).thenReturn(hostInfo);
+
+        DAOFactory daoFactory = mock(MongoDAOFactory.class);
+        when(daoFactory.getCpuStatDAO(any(HostRef.class))).thenReturn(cpuStatDAO);
+        when(daoFactory.getHostInfoDAO(any(HostRef.class))).thenReturn(hostInfoDAO);
+
+        ApplicationContext.getInstance().setDAOFactory(daoFactory);
+        HostRef ref = mock(HostRef.class);
+
+        final HostCpuView view = mock(HostCpuView.class);
+
+        // TODO: Consider to pass the ClassesView or a factory for it to the controller instead.
+        HostCpuController controller = new HostCpuController(ref) {
+            @Override
+            protected HostCpuView createView() {
+                return view;
+            }
+        };
+
+        controller.start();
+
+        try {
+            Thread.sleep(500);
+        } catch (InterruptedException e) {
+            // Get out of here ASAP.
+            return;
+        }
+
+        verify(view, atLeast(1)).addCpuLoadData(any(List.class));
+        verify(view, atLeast(1)).setCpuCount(any(String.class));
+        verify(view, atLeast(1)).setCpuModel(any(String.class));
+        // We don't verify atMost() since we might increase the update rate in the future.
+    }
+}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatConverter.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatConverter.java	Thu Mar 22 11:59:20 2012 -0400
@@ -36,7 +36,6 @@
 
 package com.redhat.thermostat.common.dao;
 
-import com.mongodb.DBObject;
 import com.redhat.thermostat.common.CpuStat;
 import com.redhat.thermostat.common.storage.Chunk;
 import com.redhat.thermostat.common.storage.Key;
@@ -52,13 +51,11 @@
         return chunk;
     }
 
-    public CpuStat fromDB(DBObject dbObj) {
-        long timestamp = (long) dbObj.get("timestamp");
-        double load5 = (Double) dbObj.get("5load");
-        double load10 = (Double) dbObj.get("10load");
-        double load15 = (Double) dbObj.get("15load");
+    public CpuStat chunkToCpuStat(Chunk chunk) {
+        long timestamp = chunk.get(Key.TIMESTAMP);
+        double load5 = chunk.get(CpuStatDAO.cpu5LoadKey);
+        double load10 = chunk.get(CpuStatDAO.cpu10LoadKey);
+        double load15 = chunk.get(CpuStatDAO.cpu15LoadKey);
         return new CpuStat(timestamp, load5, load10, load15);
     }
-
-
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAO.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAO.java	Thu Mar 22 11:59:20 2012 -0400
@@ -36,16 +36,22 @@
 
 package com.redhat.thermostat.common.dao;
 
+import java.util.List;
+
+import com.redhat.thermostat.common.CpuStat;
 import com.redhat.thermostat.common.storage.Category;
 import com.redhat.thermostat.common.storage.Key;
 
-public class CpuStatDAO {
+public interface CpuStatDAO {
 
     static Key<Double> cpu5LoadKey = new Key<>("5load", false);
     static Key<Double> cpu10LoadKey = new Key<>("10load", false);
     static Key<Double> cpu15LoadKey = new Key<>("15load", false);
 
+    static final Key<String> whereKey = new Key<>("$where", false);
+
     public static final Category cpuStatCategory = new Category("cpu-stats",
             Key.TIMESTAMP, cpu5LoadKey, cpu10LoadKey, cpu15LoadKey);
 
+    public List<CpuStat> getLatestCpuStats();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/CpuStatDAOImpl.java	Thu Mar 22 11:59:20 2012 -0400
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012 Red Hat, Inc.
+ *
+ * This file is part of Thermostat.
+ *
+ * Thermostat is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; either version 2, or (at your
+ * option) any later version.
+ *
+ * Thermostat is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Thermostat; see the file COPYING.  If not see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Linking this code with other modules is making a combined work
+ * based on this code.  Thus, the terms and conditions of the GNU
+ * General Public License cover the whole combination.
+ *
+ * As a special exception, the copyright holders of this code give
+ * you permission to link this code with independent modules to
+ * produce an executable, regardless of the license terms of these
+ * independent modules, and to copy and distribute the resulting
+ * executable under terms of your choice, provided that you also
+ * meet, for each linked independent module, the terms and conditions
+ * of the license of that module.  An independent module is a module
+ * which is not derived from or based on this code.  If you modify
+ * this code, you may extend this exception to your version of the
+ * library, but you are not obligated to do so.  If you do not wish
+ * to do so, delete this exception statement from your version.
+ */
+
+package com.redhat.thermostat.common.dao;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.redhat.thermostat.common.CpuStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
+import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
+
+class CpuStatDAOImpl implements CpuStatDAO {
+
+    private Storage storage;
+    private HostRef hostRef;
+
+    private long lastUpdate = Long.MIN_VALUE;
+
+    public CpuStatDAOImpl(Storage storage, HostRef hostRef) {
+        this.storage = storage;
+        this.hostRef = hostRef;
+    }
+
+    @Override
+    public List<CpuStat> getLatestCpuStats() {
+        ArrayList<CpuStat> result = new ArrayList<>();
+        Chunk query = new Chunk(CpuStatDAO.cpuStatCategory, false);
+        query.put(Key.AGENT_ID, hostRef.getAgentId());
+        if (lastUpdate != Long.MIN_VALUE) {
+            // TODO once we have an index and the 'column' is of type long, use
+            // a query which can utilize an index. this one doesn't
+            query.put(VmClassStatDAO.whereKey, "this.timestamp > " + lastUpdate);
+        }
+        Cursor cursor = storage.findAll(query);
+        CpuStatConverter converter = new CpuStatConverter();
+        while (cursor.hasNext()) {
+            Chunk chunk = cursor.next();
+            CpuStat stat = converter.chunkToCpuStat(chunk);
+            result.add(stat);
+            lastUpdate = Math.max(stat.getTimeStamp(), lastUpdate);
+        }
+        return result;
+    }
+
+}
--- a/common/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/DAOFactory.java	Thu Mar 22 11:59:20 2012 -0400
@@ -53,4 +53,6 @@
 
     public abstract HostInfoDAO getHostInfoDAO(HostRef ref);
 
+    public abstract CpuStatDAO getCpuStatDAO(HostRef ref);
+
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAO.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAO.java	Thu Mar 22 11:59:20 2012 -0400
@@ -49,8 +49,6 @@
     static Key<String> cpuModelKey = new Key<>("cpu_model", false);
     static Key<Long> hostMemoryTotalKey = new Key<>("memory_total", false);
 
-    static final Key<String> agentIdKey = new Key<>("agent-id", false);
-
     public static final Category hostInfoCategory = new Category("host-info",
             hostNameKey, osNameKey, osKernelKey,
             cpuCountKey, cpuModelKey, hostMemoryTotalKey);
--- a/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAOImpl.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/HostInfoDAOImpl.java	Thu Mar 22 11:59:20 2012 -0400
@@ -38,9 +38,10 @@
 
 import com.redhat.thermostat.common.HostInfo;
 import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Key;
 import com.redhat.thermostat.common.storage.Storage;
 
-public class HostInfoDAOImpl implements HostInfoDAO {
+class HostInfoDAOImpl implements HostInfoDAO {
     private HostRef ref;
     private Storage storage;
     private HostInfoConverter converter;
@@ -54,7 +55,7 @@
     @Override
     public HostInfo getHostInfo() {
         Chunk query = new Chunk(HostInfoDAO.hostInfoCategory, false);
-        query.put(HostInfoDAO.agentIdKey, ref.getAgentId());
+        query.put(Key.AGENT_ID, ref.getAgentId());
         Chunk result = storage.find(query);
         return result == null ? null : converter.chunkToHostInfo(result);
     }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/MongoDAOFactory.java	Thu Mar 22 11:59:20 2012 -0400
@@ -87,4 +87,9 @@
         return new HostInfoDAOImpl(storage, ref);
     }
 
+    @Override
+    public CpuStatDAO getCpuStatDAO(HostRef ref) {
+        return new CpuStatDAOImpl(storage, ref);
+    }
+
 }
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAO.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAO.java	Thu Mar 22 11:59:20 2012 -0400
@@ -46,13 +46,13 @@
 
     static final Key<Integer> vmIdKey = new Key<>("vm-id", false);
     static final Key<Long> loadedClassesKey = new Key<>("loadedClasses", false);
-    static final Key<String> agentIdKey = new Key<>("agent-id", false);
+
     static final Key<String> whereKey = new Key<>("$where", false);
 
 
     public static final Category vmClassStatsCategory = new Category(
             "vm-class-stats", vmIdKey, Key.TIMESTAMP, loadedClassesKey);
 
-    public abstract List<VmClassStat> getLatestClassStats();
+    public List<VmClassStat> getLatestClassStats();
 
 }
\ No newline at end of file
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAOImpl.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmClassStatDAOImpl.java	Thu Mar 22 11:59:20 2012 -0400
@@ -45,7 +45,7 @@
 import com.redhat.thermostat.common.storage.Key;
 import com.redhat.thermostat.common.storage.Storage;
 
-public class VmClassStatDAOImpl implements VmClassStatDAO {
+class VmClassStatDAOImpl implements VmClassStatDAO {
 
     private VmRef ref;
     private Storage storage;
@@ -61,7 +61,7 @@
     public List<VmClassStat> getLatestClassStats() {
         ArrayList<VmClassStat> result = new ArrayList<>();
         Chunk query = new Chunk(VmClassStatDAO.vmClassStatsCategory, false);
-        query.put(VmClassStatDAO.agentIdKey, ref.getAgent().getAgentId());
+        query.put(Key.AGENT_ID, ref.getAgent().getAgentId());
         query.put(VmClassStatDAO.vmIdKey, Integer.valueOf(ref.getId()));
         if (lastUpdate != Long.MIN_VALUE) {
             // TODO once we have an index and the 'column' is of type long, use
--- a/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAO.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/common/src/main/java/com/redhat/thermostat/common/dao/VmMemoryStatDAO.java	Thu Mar 22 11:59:20 2012 -0400
@@ -43,7 +43,6 @@
 public abstract class VmMemoryStatDAO {
 
     static final Key<Integer> vmIdKey = new Key<>("vm-id", false);
-    static final Key<String> agentIdKey = new Key<>("agent-id", false);
 
     static final Key<String> vmMemoryStatEdenGenKey = new Key<>("eden.gen", false);
     static final Key<String> vmMemoryStatEdenCollectorKey = new Key<>("eden.collector", false);
--- a/common/src/main/java/com/redhat/thermostat/common/storage/Key.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/common/src/main/java/com/redhat/thermostat/common/storage/Key.java	Thu Mar 22 11:59:20 2012 -0400
@@ -42,7 +42,7 @@
  */
 public class Key<T> {
 
-    // Key used by most Categories.
+    // Keys used by most Categories.
     public static Key<Long> TIMESTAMP = new Key<>("timestamp", false);
     public static Key<String> AGENT_ID = new Key<>("agent-id", false);
 
--- a/common/src/test/java/com/redhat/thermostat/common/dao/CpuStatConverterTest.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/CpuStatConverterTest.java	Thu Mar 22 11:59:20 2012 -0400
@@ -52,13 +52,24 @@
         Chunk chunk = new CpuStatConverter().cpuStatToChunk(stat);
         assertNotNull(chunk);
         assertEquals("cpu-stats", chunk.getCategory().getName());
-        assertEquals((Long) 10L, chunk.get(new Key<Long>("timestamp", false)));
-        assertEquals(5.0, chunk.get(new Key<Double>("5load", false)), 0.001);
-        assertEquals(10.0, chunk.get(new Key<Double>("10load", false)), 0.001);
-        assertEquals(15.0, chunk.get(new Key<Double>("15load", false)), 0.001);
-
+        assertEquals((Long) 10L, chunk.get(Key.TIMESTAMP));
+        assertEquals(5.0, chunk.get(CpuStatDAO.cpu5LoadKey), 0.001);
+        assertEquals(10.0, chunk.get(CpuStatDAO.cpu10LoadKey), 0.001);
+        assertEquals(15.0, chunk.get(CpuStatDAO.cpu15LoadKey), 0.001);
     }
 
-    // TODO test conversion the other way too
-
+    @Test
+    public void testChunkToCpuStat() {
+        Chunk chunk = new Chunk(CpuStatDAO.cpuStatCategory, false);
+        chunk.put(Key.TIMESTAMP, 10L);
+        chunk.put(CpuStatDAO.cpu5LoadKey, 5.0);
+        chunk.put(CpuStatDAO.cpu10LoadKey, 10.0);
+        chunk.put(CpuStatDAO.cpu15LoadKey, 15.0);
+        CpuStat stat = new CpuStatConverter().chunkToCpuStat(chunk);
+        assertNotNull(stat);
+        assertEquals(10L, stat.getTimeStamp());
+        assertEquals(5.0, stat.getLoad5(), 0.001);
+        assertEquals(10.0, stat.getLoad10(), 0.001);
+        assertEquals(15.0, stat.getLoad15(), 0.001);
+    }
 }
--- a/common/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/CpuStatDAOTest.java	Thu Mar 22 11:59:20 2012 -0400
@@ -37,14 +37,29 @@
 package com.redhat.thermostat.common.dao;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import java.util.Collection;
+import java.util.List;
 
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+
+import com.redhat.thermostat.common.CpuStat;
+import com.redhat.thermostat.common.storage.Chunk;
+import com.redhat.thermostat.common.storage.Cursor;
 import com.redhat.thermostat.common.storage.Key;
+import com.redhat.thermostat.common.storage.Storage;
 
 public class CpuStatDAOTest {
 
+    @Test
     public void testCategory() {
         assertEquals("cpu-stats", CpuStatDAO.cpuStatCategory.getName());
         Collection<Key<?>> keys = CpuStatDAO.cpuStatCategory.getKeys();
@@ -55,4 +70,64 @@
         assertEquals(4, keys.size());
     }
 
+    @Test
+    public void testGetLatestCpuStats() {
+        Chunk chunk = new Chunk(CpuStatDAO.cpuStatCategory, false);
+        chunk.put(Key.TIMESTAMP, 1234L);
+        chunk.put(CpuStatDAO.cpu5LoadKey, 5.0);
+        chunk.put(CpuStatDAO.cpu10LoadKey, 10.0);
+        chunk.put(CpuStatDAO.cpu15LoadKey, 15.0);
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        CpuStatDAO dao = new CpuStatDAOImpl(storage, hostRef);
+        List<CpuStat> cpuStats = dao.getLatestCpuStats();
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage).findAll(arg.capture());
+        assertNull(arg.getValue().get(new Key<String>("$where", false)));
+
+        assertEquals(1, cpuStats.size());
+        CpuStat stat = cpuStats.get(0);
+        assertEquals(1234L, stat.getTimeStamp());
+        assertEquals(5.0, stat.getLoad5(), 0.001);
+        assertEquals(10.0, stat.getLoad10(), 0.001);
+        assertEquals(15.0, stat.getLoad15(), 0.001);
+    }
+
+    @Test
+    public void testGetLatestCpuStatsTwice() {
+        Chunk chunk = new Chunk(CpuStatDAO.cpuStatCategory, false);
+        chunk.put(Key.TIMESTAMP, 1234L);
+        chunk.put(CpuStatDAO.cpu5LoadKey, 5.0);
+        chunk.put(CpuStatDAO.cpu10LoadKey, 10.0);
+        chunk.put(CpuStatDAO.cpu15LoadKey, 15.0);
+
+        Cursor cursor = mock(Cursor.class);
+        when(cursor.hasNext()).thenReturn(true).thenReturn(false);
+        when(cursor.next()).thenReturn(chunk);
+
+        Storage storage = mock(Storage.class);
+        when(storage.findAll(any(Chunk.class))).thenReturn(cursor);
+
+        HostRef hostRef = mock(HostRef.class);
+        when(hostRef.getAgentId()).thenReturn("system");
+
+        CpuStatDAO dao = new CpuStatDAOImpl(storage, hostRef);
+        dao.getLatestCpuStats();
+        dao.getLatestCpuStats();
+
+        ArgumentCaptor<Chunk> arg = ArgumentCaptor.forClass(Chunk.class);
+        verify(storage, times(2)).findAll(arg.capture());
+        assertEquals("this.timestamp > 1234", arg.getValue().get(new Key<String>("$where", false)));
+    }
+
 }
--- a/common/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java	Thu Mar 22 16:45:55 2012 +0100
+++ b/common/src/test/java/com/redhat/thermostat/common/dao/MongoDAOFactoryTest.java	Thu Mar 22 11:59:20 2012 -0400
@@ -77,4 +77,39 @@
         assertNotNull(vmClassStatsDAO);
     }
 
+    @Test
+    public void testGetHostInfoDAO() {
+        DB db = mock(DB.class);
+
+        MongoConnection conn = mock(MongoConnection.class);
+        when(conn.getDB()).thenReturn(db);
+
+        ConnectionProvider connProv = mock(ConnectionProvider.class);
+        when(connProv.createConnection()).thenReturn(conn);
+
+        DAOFactory instance = new MongoDAOFactory(connProv);
+
+        HostRef ref = mock(HostRef.class);
+        HostInfoDAO dao = instance.getHostInfoDAO(ref);
+
+        assertNotNull(dao);
+    }
+
+    @Test
+    public void testGetCpuStatDAO() {
+        DB db = mock(DB.class);
+
+        MongoConnection conn = mock(MongoConnection.class);
+        when(conn.getDB()).thenReturn(db);
+
+        ConnectionProvider connProv = mock(ConnectionProvider.class);
+        when(connProv.createConnection()).thenReturn(conn);
+
+        DAOFactory instance = new MongoDAOFactory(connProv);
+
+        HostRef ref = mock(HostRef.class);
+        CpuStatDAO dao = instance.getCpuStatDAO(ref);
+
+        assertNotNull(dao);
+    }
 }