/***************************************************************************
* Copyright 2006-2016 by Christian Ihle *
* contact@kouchat.net *
* *
* This file is part of KouChat. *
* *
* KouChat is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation, either version 3 of *
* the License, or (at your option) any later version. *
* *
* KouChat 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 *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with KouChat. *
* If not, see <http://www.gnu.org/licenses/>. *
***************************************************************************/
package net.usikkert.kouchat.util;
import static org.junit.Assert.*;
import org.junit.Before;
import org.junit.Test;
/**
* Test of {@link ByteCounter}.
*
* @author Christian Ihle
*/
public class ByteCounterTest {
/** The byte counter being tested. */
private ByteCounter counter;
/**
* Creates a new byte counter before each test.
*/
@Before
public void createByteCounter() {
counter = new ByteCounter();
}
/**
* Tests that the number of bytes per second isn't calculated before
* a full second has passed.
*/
@Test
public void testNoCalculationBeforeSecond() {
final long bytesAdded = 1024;
final long currentTime = 999;
final long timeSpent = counter.updateTimeSpent(currentTime);
assertEquals(999, timeSpent);
counter.updateCounters(bytesAdded, timeSpent);
assertEquals(0, counter.getBytesPerSec());
assertEquals(1024, counter.getBytesCounted());
assertEquals(999, counter.getTimeCounted());
}
/**
* Tests that the number of bytes per second is calculated
* when exactly one second has passed, and that the counters
* are reset since no time is left.
*/
@Test
public void testCalculationAfterOneSecond() {
final long bytesAdded = 1024;
final long currentTime = 1000;
final long timeSpent = counter.updateTimeSpent(currentTime);
assertEquals(1000, timeSpent);
counter.updateCounters(bytesAdded, timeSpent);
assertEquals(1024, counter.getBytesPerSec());
assertEquals(0, counter.getBytesCounted());
assertEquals(0, counter.getTimeCounted());
}
/**
* Tests that the counters and calculations are correct when 3
* updates are needed to fill a whole second.
*/
@Test
public void testWith3Updates() {
final long bytesAdded = 1024;
final long currentTime1 = 300;
final long timeSpent1 = counter.updateTimeSpent(currentTime1);
assertEquals(300, timeSpent1);
counter.updateCounters(bytesAdded, timeSpent1);
assertEquals(0, counter.getBytesPerSec());
assertEquals(1024, counter.getBytesCounted());
assertEquals(300, counter.getTimeCounted());
final long currentTime2 = 750;
final long timeSpent2 = counter.updateTimeSpent(currentTime2);
assertEquals(450, timeSpent2);
counter.updateCounters(bytesAdded, timeSpent2);
assertEquals(0, counter.getBytesPerSec());
assertEquals(2048, counter.getBytesCounted());
assertEquals(750, counter.getTimeCounted());
final long currentTime3 = 1000;
final long timeSpent3 = counter.updateTimeSpent(currentTime3);
assertEquals(250, timeSpent3);
counter.updateCounters(bytesAdded, timeSpent3);
assertEquals(3072, counter.getBytesPerSec());
assertEquals(0, counter.getBytesCounted());
assertEquals(0, counter.getTimeCounted());
}
/**
* Tests updates happening over 2 seconds, and checking that every
* second the counters are reset and the speed is calculated.
*/
@Test
public void testCountersResetBetweenCalculations() {
final long bytesAdded = 1024;
final long currentTime1 = 500;
final long timeSpent1 = counter.updateTimeSpent(currentTime1);
assertEquals(500, timeSpent1);
counter.updateCounters(bytesAdded, timeSpent1);
assertEquals(0, counter.getBytesPerSec());
assertEquals(1024, counter.getBytesCounted());
assertEquals(500, counter.getTimeCounted());
final long currentTime2 = 1000;
final long timeSpent2 = counter.updateTimeSpent(currentTime2);
assertEquals(500, timeSpent2);
counter.updateCounters(bytesAdded, timeSpent2);
assertEquals(2048, counter.getBytesPerSec());
assertEquals(0, counter.getBytesCounted());
assertEquals(0, counter.getTimeCounted());
final long currentTime3 = 1500;
final long timeSpent3 = counter.updateTimeSpent(currentTime3);
assertEquals(500, timeSpent3);
counter.updateCounters(bytesAdded, timeSpent3);
assertEquals(2048, counter.getBytesPerSec());
assertEquals(1024, counter.getBytesCounted());
assertEquals(500, counter.getTimeCounted());
final long currentTime4 = 2000;
final long timeSpent4 = counter.updateTimeSpent(currentTime4);
assertEquals(500, timeSpent4);
counter.updateCounters(bytesAdded, timeSpent4);
assertEquals(2048, counter.getBytesPerSec());
assertEquals(0, counter.getBytesCounted());
assertEquals(0, counter.getTimeCounted());
}
/**
* Tests that the calculations handle too much time spent.
*
* <p>What happens in the third update is that 1024 bytes is added
* in 400ms, but since 900ms is already registered only the bytes
* added in the first 100ms (256 bytes) is used in the calculation and
* the rest is saved for the next update.</p>
*/
@Test
public void testHandlingOfTimeLeft() {
final long bytesAdded = 1024;
final long currentTime1 = 300;
final long timeSpent1 = counter.updateTimeSpent(currentTime1);
assertEquals(300, timeSpent1);
counter.updateCounters(bytesAdded, timeSpent1);
assertEquals(0, counter.getBytesPerSec());
assertEquals(1024, counter.getBytesCounted());
assertEquals(300, counter.getTimeCounted());
final long currentTime2 = 900;
final long timeSpent2 = counter.updateTimeSpent(currentTime2);
assertEquals(600, timeSpent2);
counter.updateCounters(bytesAdded, timeSpent2);
assertEquals(0, counter.getBytesPerSec());
assertEquals(2048, counter.getBytesCounted());
assertEquals(900, counter.getTimeCounted());
final long currentTime3 = 1300;
final long timeSpent3 = counter.updateTimeSpent(currentTime3);
assertEquals(400, timeSpent3);
counter.updateCounters(bytesAdded, timeSpent3);
assertEquals(2304, counter.getBytesPerSec());
assertEquals(768, counter.getBytesCounted());
assertEquals(300, counter.getTimeCounted());
final long currentTime4 = 2000;
final long timeSpent4 = counter.updateTimeSpent(currentTime4);
assertEquals(700, timeSpent4);
counter.updateCounters(bytesAdded, timeSpent4);
assertEquals(1792, counter.getBytesPerSec());
assertEquals(0, counter.getBytesCounted());
assertEquals(0, counter.getTimeCounted());
}
/**
* The speed should be the same for both seconds this time,
* since the 1024 bytes added in middle should be split equally
* between the first and the second calculation.
*/
@Test
public void testHandlingOfTimeLeftWithLargerUpdate() {
final long bytesAdded = 1024;
final long currentTime1 = 500;
final long timeSpent1 = counter.updateTimeSpent(currentTime1);
assertEquals(500, timeSpent1);
counter.updateCounters(bytesAdded, timeSpent1);
assertEquals(0, counter.getBytesPerSec());
assertEquals(1024, counter.getBytesCounted());
assertEquals(500, counter.getTimeCounted());
final long currentTime2 = 1500;
final long timeSpent2 = counter.updateTimeSpent(currentTime2);
assertEquals(1000, timeSpent2);
counter.updateCounters(bytesAdded, timeSpent2);
assertEquals(1536, counter.getBytesPerSec());
assertEquals(512, counter.getBytesCounted());
assertEquals(500, counter.getTimeCounted());
final long currentTime3 = 2000;
final long timeSpent3 = counter.updateTimeSpent(currentTime3);
assertEquals(500, timeSpent3);
counter.updateCounters(bytesAdded, timeSpent3);
assertEquals(1536, counter.getBytesPerSec());
assertEquals(0, counter.getBytesCounted());
assertEquals(0, counter.getTimeCounted());
}
/**
* When it takes more than one second between updates,
* only the bytes added last is used in the calculation. The extra
* time and bytes are not saved for later.
*
* <p>In this case 1024 bytes added in 2.3 seconds gives 445 KB/s.</p>
*/
@Test
public void testLongPauseInUpdates() {
final long bytesAdded = 1024;
final long currentTime1 = 200;
final long timeSpent1 = counter.updateTimeSpent(currentTime1);
assertEquals(200, timeSpent1);
counter.updateCounters(bytesAdded, timeSpent1);
assertEquals(0, counter.getBytesPerSec());
assertEquals(1024, counter.getBytesCounted());
assertEquals(200, counter.getTimeCounted());
final long currentTime2 = 2500;
final long timeSpent2 = counter.updateTimeSpent(currentTime2);
assertEquals(2300, timeSpent2);
counter.updateCounters(bytesAdded, timeSpent2);
assertEquals(445, counter.getBytesPerSec());
assertEquals(0, counter.getTimeCounted());
assertEquals(0, counter.getBytesCounted());
}
/**
* Tests the handling of long pause when it's the first
* update and just a little bit too long.
*/
@Test
public void testJustALittleBitTooLong() {
final long bytesAdded = 1024;
final long currentTime = 1100;
final long timeSpent = counter.updateTimeSpent(currentTime);
assertEquals(1100, timeSpent);
counter.updateCounters(bytesAdded, timeSpent);
assertEquals(930, counter.getBytesPerSec());
assertEquals(0, counter.getBytesCounted());
assertEquals(0, counter.getTimeCounted());
}
/**
* Another test of long pause, but with nice logical round numbers. :)
*/
@Test
public void testTwoSecondUpdate() {
final long bytesAdded = 1024;
final long currentTime = 2000;
final long timeSpent = counter.updateTimeSpent(currentTime);
assertEquals(2000, timeSpent);
counter.updateCounters(bytesAdded, timeSpent);
assertEquals(512, counter.getBytesPerSec());
assertEquals(0, counter.getTimeCounted());
assertEquals(0, counter.getBytesCounted());
}
/**
* Tests a very slow file transfer, with 1 KB counted every 4 milliseconds
* for exactly one second. Which gives a speed of 250 KB/s.
*/
@Test
public void testVerySlowTransfer() {
final long bytesAdded = 1024;
for (int i = 1; i <= 250; i++) {
final long timeSpent = counter.updateTimeSpent(i * 4);
assertEquals(4, timeSpent);
counter.updateCounters(bytesAdded, timeSpent);
if (i < 250) {
assertEquals(1024 * i, counter.getBytesCounted());
assertEquals(i * 4, counter.getTimeCounted());
}
}
assertEquals(256000, counter.getBytesPerSec());
assertEquals(0, counter.getBytesCounted());
assertEquals(0, counter.getTimeCounted());
}
/**
* Tests a slow file transfer, with 1 KB counted every millisecond
* for exactly one second. Which gives a speed of 1.000 KB/s.
*/
@Test
public void testSlowTransfer() {
final long bytesAdded = 1024;
for (int i = 1; i <= 1000; i++) {
final long timeSpent = counter.updateTimeSpent(i);
assertEquals(1, timeSpent);
counter.updateCounters(bytesAdded, timeSpent);
if (i < 1000) {
assertEquals(1024 * i, counter.getBytesCounted());
assertEquals(i, counter.getTimeCounted());
}
}
assertEquals(1024000, counter.getBytesPerSec());
assertEquals(0, counter.getBytesCounted());
assertEquals(0, counter.getTimeCounted());
}
/**
* Tests a fast file transfer, with 1 KB counted 10 times every millisecond
* for exactly one second. Which gives a speed of 10.000 KB/s (9,77 MB/s).
*/
@Test
public void testFastTransfer() {
final long bytesAdded = 1024;
int time = 0;
for (int i = 1; time < 1000; i++) {
final boolean addTime = (i % 10 == 0 ? true : false);
if (addTime) {
time++;
}
final long timeSpent = counter.updateTimeSpent(time);
if (addTime) {
assertEquals(1, timeSpent);
} else {
assertEquals(0, timeSpent);
}
counter.updateCounters(bytesAdded, timeSpent);
if (time < 1000) {
assertEquals(1024 * i, counter.getBytesCounted());
assertEquals(time, counter.getTimeCounted());
}
}
assertEquals(10240000, counter.getBytesPerSec());
assertEquals(0, counter.getBytesCounted());
assertEquals(0, counter.getTimeCounted());
}
/**
* Tests a very fast file transfer, with 1 KB counted 50 times every millisecond
* for exactly one second. Which gives a speed of 50.000 KB/s (48,83 MB/s).
*/
@Test
public void testVeryFastTransfer() {
final long bytesAdded = 1024;
int time = 0;
for (int i = 1; time < 1000; i++) {
final boolean addTime = (i % 50 == 0 ? true : false);
if (addTime) {
time++;
}
final long timeSpent = counter.updateTimeSpent(time);
if (addTime) {
assertEquals(1, timeSpent);
} else {
assertEquals(0, timeSpent);
}
counter.updateCounters(bytesAdded, timeSpent);
if (time < 1000) {
assertEquals(1024 * i, counter.getBytesCounted());
assertEquals(time, counter.getTimeCounted());
}
}
assertEquals(51200000, counter.getBytesPerSec());
assertEquals(0, counter.getBytesCounted());
assertEquals(0, counter.getTimeCounted());
}
/**
* Tests that adding bytes the official way works.
*
* <p>It's not easy to make a verification of the result in a consistent
* way since we are dealing with time, so the test just checks that
* adding bytes leads to a calculation at some point. This should take
* about one second.</p>
*/
@Test
public void testOfficialAPIWorks() {
final long bytesAdded = 1024;
counter.prepare();
while (counter.getBytesPerSec() == 0) {
counter.addBytes(bytesAdded);
}
}
}