/** Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016. All rights reserved. Contact: SYSTAP, LLC DBA Blazegraph 2501 Calvert ST NW #106 Washington, DC 20008 licenses@blazegraph.com 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; version 2 of the License. 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 */ /* * Created on Apr 30, 2010 */ package com.bigdata.counters.striped; import junit.framework.TestCase2; import com.bigdata.counters.CounterSet; import com.bigdata.counters.Instrument; /** * Unit tests for {@link StripedCounters}. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ */ public class TestStripedCounters extends TestCase2 { /** * */ public TestStripedCounters() { } /** * @param name */ public TestStripedCounters(String name) { super(name); } /** * Sample implementation used for the unit tests. * * @author <a href="mailto:thompsonbry@users.sourceforge.net">Bryan Thompson</a> * @version $Id$ * @param <T> */ static private class StoreCounters<T extends StoreCounters<T>> extends StripedCounters<T> { /** * Performance counter used by the unit tests. */ public volatile long nreads; /** * {@inheritDoc} */ public StoreCounters() { super(); } /** * {@inheritDoc} */ public StoreCounters(int batchSize) { super(batchSize); } /** * {@inheritDoc} */ public StoreCounters(int nstripes, int batchSize) { super(nstripes, batchSize); } @Override public void add(final T o) { super.add(o); nreads += o.nreads; } @Override public T subtract(final T o) { // make a copy of the current counters. final T t = super.subtract(o); // subtract out the given counters. t.nreads -= o.nreads; return t; } @Override public void clear() { // subtract out the given counters. nreads = 0; } @Override public CounterSet getCounters() { final CounterSet root = super.getCounters(); root.addCounter("nreads", new Instrument<Long>() { public void sample() { setValue(nreads); } }); return root; } } /** * A basic unit test verifies that a child "strip" is accessed by acquire() * and that the updates are only pushed to the parent counters object every * batchSize release()s. * * @todo do a multi-threaded unit test. */ public void test_stripedCounters() { final int nstripes = 3; final int batchSize = 5; final StoreCounters<?> c = new StoreCounters(nstripes, batchSize); // do batchSize-1 updates and verify no change in the outer instance. for (int i = 1; i < batchSize; i++) { final StoreCounters<?> t = (StoreCounters<?>) c.acquire(); if (t == c) fail("returned the parent instead of the child."); t.nreads++; t.release(); if (log.isInfoEnabled()) log.info("pass=" + i + ", value=" + c.nreads); if (c.nreads != 0) fail("updated on pass: i=" + i + ", value=" + c.nreads); } // do one more update and verify outer instance has changed. { final StoreCounters<?> t = (StoreCounters<?>) c.acquire(); t.nreads++; t.release(); if (log.isInfoEnabled()) log.info("pass=" + batchSize + ", value=" + c.nreads); if (c.nreads == 0) fail("Counter value was not updated."); assertEquals(c.nreads, batchSize); } // do batchSize-1 updates and verify no change in the outer instance. if (log.isInfoEnabled()) log.info("-----------------"); final long lastValue = c.nreads; for (int i = 1; i < batchSize; i++) { final StoreCounters<?> t = (StoreCounters<?>) c.acquire(); if (t == c) fail("returned the parent instead of the child."); t.nreads++; t.release(); if (log.isInfoEnabled()) log.info("pass=" + i + ", value=" + c.nreads); if (c.nreads != lastValue) fail("updated on pass: i=" + i + ", value=" + c.nreads); } // do one more update and verify outer instance has changed. { final StoreCounters<?> t = (StoreCounters<?>) c.acquire(); t.nreads++; t.release(); if (log.isInfoEnabled()) log.info("pass=" + batchSize + ", value=" + c.nreads); if (c.nreads == lastValue) fail("Counter value was not updated."); assertEquals(c.nreads, batchSize * 2); } } }