// BlogBridge -- RSS feed reader, manager, and web based service // Copyright (C) 2002-2007 by R. Pito Salas // // This program 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 of the License, or (at your option) any later version. // // This program 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 this program; // if not, write to the Free Software Foundation, Inc., 59 Temple Place, // Suite 330, Boston, MA 02111-1307 USA // // Contact: R. Pito Salas // mailto:pitosalas@users.sourceforge.net // More information: about BlogBridge // http://www.blogbridge.com // http://sourceforge.net/projects/blogbridge // // $Id: TestHsqlPersistenceManagerReadPinStats.java,v 1.4 2007/10/04 08:49:53 spyromus Exp $ // package com.salas.bb.persistence.backend; import com.salas.bb.persistence.PersistenceException; import com.salas.bb.persistence.domain.CountStats; import com.salas.bb.persistence.domain.ReadStats; import com.salas.bb.utils.Constants; import com.salas.bb.utils.DateUtils; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.List; /** Testing marking articles read and pinned in feeds and guides, and making reports. */ public class TestHsqlPersistenceManagerReadPinStats extends TestHsqlPersistenceManagerStats { /** Tests reading an article in a feed. */ public void testRead() { // Mark an article and provide a guide and a feed pm.articlesRead(guide, feed, 1); // Check assertFeedReadStats(1); assertGuideReadStats(1); assertReadPerWeekday(1); // Mark an article again pm.articlesRead(guide, feed, 2); // Check assertFeedReadStats(3); assertGuideReadStats(3); assertReadPerWeekday(3); } /** Tests pinning an article in a feed. */ public void testPin() { // Pin an article pm.articlesPinned(guide, feed, 1); // Check assertFeedPinStats(1); assertGuidePinStats(1); // Pin again pm.articlesPinned(guide, feed, 2); // Check assertFeedPinStats(3); assertGuidePinStats(3); } /** Tests reading an article when no feed selected. */ public void testReadNoFeedSelected() { // Mark an article and provide a guide pm.articlesRead(guide, null, 1); // Check assertFeedReadStats(); assertGuideReadStats(1); assertReadPerWeekday(1); // Mark an article again pm.articlesRead(guide, null, 1); // Check assertFeedReadStats(); assertGuideReadStats(2); assertReadPerWeekday(2); } /** Tests pinning an article when no feed selected. */ public void testPinNoFeedSelected() { // Pin an article pm.articlesPinned(guide, null, 1); // Check assertFeedPinStats(); assertGuidePinStats(1); // Pin again pm.articlesPinned(guide, null, 1); // Check assertFeedPinStats(); assertGuidePinStats(2); } /** Tests reading an article when no guide selected. */ public void testReadNoGuideSelected() { // Mark an article and provide a guide and a feed pm.articlesRead(null, null, 1); // Check assertFeedReadStats(); assertGuideReadStats(); assertReadPerWeekday(1); // Mark an article again pm.articlesRead(null, null, 1); // Check assertFeedReadStats(); assertGuideReadStats(); assertReadPerWeekday(2); } /** Tests pinning an article when no guide selected. */ public void testPinNoGuideSelected() { // Pin an article pm.articlesPinned(null, null, 1); // Check assertFeedPinStats(); assertGuidePinStats(); // Pin again pm.articlesPinned(null, null, 1); // Check assertFeedPinStats(); assertGuidePinStats(); } /** Tests acting upon resetting stats. Nothing should happen. */ public void testReset() { // Mark an article and provide a guide and a feed pm.articlesRead(guide, feed, 1); pm.articlesPinned(guide, feed, 1); // Check assertFeedReadStats(1); assertGuideReadStats(1); assertFeedPinStats(1); assertGuidePinStats(1); // Reset stats pm.reset(); // Check -- nothing should be reset assertFeedReadStats(1); assertGuideReadStats(1); assertFeedPinStats(1); assertGuidePinStats(1); } /** Tests automatically removing old records from the database. */ public void testRemovingOldRecords() { // Add a year old records long today = DateUtils.getTodayTime(); long yearAgo = today - Constants.MILLIS_IN_YEAR; insertReadStatRecord("FEEDREADSTATS", feed.getID(), yearAgo); insertReadStatRecord("GUIDEREADSTATS", guide.getID(), yearAgo); insertReadStatRecord("FEEDPINSTATS", feed.getID(), yearAgo); insertReadStatRecord("GUIDEPINSTATS", guide.getID(), yearAgo); // Add today's pins and reads pm.articlesRead(guide, feed, 1); pm.articlesPinned(guide, feed, 1); // Check they are present assertRecordsCount(1, "FEEDREADSTATS"); assertRecordsCount(1, "GUIDEREADSTATS"); assertRecordsCount(1, "FEEDPINSTATS"); assertRecordsCount(1, "GUIDEPINSTATS"); assertGuideReadStats(1); assertFeedReadStats(1); assertFeedPinStats(1); assertGuidePinStats(1); } /** * Inserts a stat record in a table. * * @param table table. * @param id object id. * @param time time. */ private void insertReadStatRecord(String table, long id, long time) { try { PreparedStatement stmt = pm.getPreparedStatement( "INSERT INTO " + table + " (ID, TS, CNT) VALUES (?, ?, 1)"); stmt.setLong(1, id); stmt.setLong(2, time); assertEquals("Record wasn't added to " + table, 1, stmt.executeUpdate()); } catch (SQLException e) { e.printStackTrace(); fail("Failed to insert the record into " + table); } } /** * Asserts that read stats for a feed match the expectations. * The stats module returns values in the earlier date first order, * where's the parameter is in the latest date first order (reverse) * for the greater convenience. * * @param counts counts. */ private void assertFeedReadStats(Integer ... counts) { try { List<ReadStats> stats = pm.getFeedsReadStats(); assertEntityReadStats(feed.getID(), stats, counts); } catch (PersistenceException e) { e.printStackTrace(); fail("Failed to fetch"); } } /** * Asserts that pin stats for a feed match the expectations. * The stats module returns values in the earlier date first order, * where's the parameter is in the latest date first order (reverse) * for the greater convenience. * * @param counts counts. */ private void assertFeedPinStats(Integer ... counts) { try { List<ReadStats> stats = pm.getFeedsPinStats(); assertEntityReadStats(feed.getID(), stats, counts); } catch (PersistenceException e) { e.printStackTrace(); fail("Failed to fetch"); } } /** * Asserts that read stats for a guide match the expectations. * The stats module returns values in the earlier date first order, * where's the parameter is in the latest date first order (reverse) * for the greater convenience. * * @param counts counts. */ private void assertGuideReadStats(Integer ... counts) { try { List<ReadStats> stats = pm.getGuidesReadStats(); assertEntityReadStats(feed.getID(), stats, counts); } catch (PersistenceException e) { e.printStackTrace(); fail("Failed to fetch"); } } /** * Asserts that pin stats for a guide match the expectations. * The stats module returns values in the earlier date first order, * where's the parameter is in the latest date first order (reverse) * for the greater convenience. * * @param counts counts. */ private void assertGuidePinStats(Integer ... counts) { try { List<ReadStats> stats = pm.getGuidesPinStats(); assertEntityReadStats(feed.getID(), stats, counts); } catch (PersistenceException e) { e.printStackTrace(); fail("Failed to fetch"); } } /** * Asserts that the stats contain the record for a given entity and they * match the given counts. * * @param objectId entity id. * @param stats stats to check. * @param counts counts to verify against. */ private static void assertEntityReadStats(long objectId, List<ReadStats> stats, Integer ... counts) { for (ReadStats stat : stats) { if (stat.getObjectId() == objectId) { int[] oc = stat.getCounts(); long[] ti = stat.getTimes(); // Check that the length is fine assertEquals("Wrong number of items.", HsqlPersistenceManager.STAT_LAST_N_DAYS, oc.length); assertEquals("Wrong number of items.", HsqlPersistenceManager.STAT_LAST_N_DAYS, ti.length); // Check that all important values match // (back to front) int i = 0; for (Integer count : counts) { int c = oc[oc.length - i - 1]; long t = ti[ti.length - i - 1]; assertEquals("Wrong count", count.intValue(), c); assertEquals("Wrong time", DateUtils.getTodayTime() - i * Constants.MILLIS_IN_DAY, t); i++; } return; } } if (counts.length > 0) fail("Stats for the given feed were not found"); } /** * Makes sure todays record has the given count. * * @param count count. */ private void assertReadPerWeekday(int count) { // Get current day Calendar cal = new GregorianCalendar(); int day = cal.get(Calendar.DAY_OF_WEEK) - Calendar.SUNDAY; try { CountStats[] stats = pm.getItemsReadPerWeekday(); assertEquals(Constants.DAYS_IN_WEEK, stats.length); for (int i = 0; i < Constants.DAYS_IN_WEEK; i++) { assertEquals(i == day ? count : 0, stats[i].getCountTotal()); assertEquals(i == day ? count : 0, stats[i].getCountReset()); } } catch (PersistenceException e) { e.printStackTrace(); fail("Failed to check"); } } /** * Asserts that a table has a given number of records. * * @param cnt count. * @param table target table. */ private void assertRecordsCount(int cnt, String table) { try { PreparedStatement stmt = pm.getPreparedStatement("SELECT COUNT(*) FROM " + table); ResultSet rs = stmt.executeQuery(); if (rs.next()) { assertEquals(cnt, rs.getInt(1)); } else { fail("No counts for the " + table); } } catch (SQLException e) { e.printStackTrace(); fail("Failed to assert record counts"); } } }