/* * Copyright (C) 2012, Katy Hilgenberg. * Special acknowledgments to: Knowledge & Data Engineering Group, University of Kassel (http://www.kde.cs.uni-kassel.de). * Contact: sdcf@cs.uni-kassel.de * * This file is part of the SDCFramework (Sensor Data Collection Framework) project. * * The SDCFramework 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. * * The SDCFramework 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 the SDCFramework. If not, see <http://www.gnu.org/licenses/>. */ package de.unikassel.android.sdcframework.devices.tests; import de.unikassel.android.sdcframework.data.Sample; import de.unikassel.android.sdcframework.data.tests.TestGPSSampleData; import de.unikassel.android.sdcframework.data.tests.TestSampleCollection; import de.unikassel.android.sdcframework.devices.SampleTakingDeviceScanner; import de.unikassel.android.sdcframework.devices.facade.SampleProvidingSensorDevice; import de.unikassel.android.sdcframework.devices.facade.SensorDeviceIdentifier; import de.unikassel.android.sdcframework.test.DelegatingMockContext; import de.unikassel.android.sdcframework.test.TestUtils; import de.unikassel.android.sdcframework.util.tests.SampleEventObserverForTest; import android.content.Context; import android.os.Handler; import android.test.AndroidTestCase; /** * Tests for the abstract sample taking device scanner base class. * * @author Katy Hilgenberg * */ public class TestSampleTakingDeviceScanner extends AndroidTestCase { /* * (non-Javadoc) * * @see junit.framework.TestCase#setUp() */ @Override protected void setUp() throws Exception { setContext( new DelegatingMockContext( getContext() ) ); super.setUp(); } /* (non-Javadoc) * @see android.test.AndroidTestCase#tearDown() */ @Override protected void tearDown() throws Exception { super.tearDown(); } /** * A test implementation of a sensor device implementing the * SampleProvidingSensorDevice interface * * @author Katy Hilgenberg * */ private class SampleProvidingSensorDeviceForTest extends AbstractSensorDeviceForTest implements SampleProvidingSensorDevice { /** * The current sample */ public Sample currentSample = null; /** * Flag if a new simple sensor device sample with just a time stamp set * shall be created in take sample ( if false just currentSample is returned * ) */ public boolean doCreateSampleWithTimeStamp = false; /** * Constructor * * @param deviceId * the device id */ public SampleProvidingSensorDeviceForTest( SensorDeviceIdentifier deviceId ) { super( deviceId ); } /* * (non-Javadoc) * * @see * de.unikassel.android.sdcframework.devices.facade.SampleProvidingSensorDevice * #getSample() */ @Override public Sample getSample() { if ( doCreateSampleWithTimeStamp ) { Sample sample = new Sample(); sample.setTimeStamp( System.currentTimeMillis() ); return sample; } return currentSample; } /* (non-Javadoc) * @see de.unikassel.android.sdcframework.devices.facade.SampleProvidingSensorDevice#hasSample() */ @Override public boolean hasSample() { return true; } } /** * A test implementation of a scanner extending SampleTakingDeviceScanner * * @author Katy Hilgenberg * */ private class SampleTakingDeviceScannerForTest extends SampleTakingDeviceScanner { /** * Flag for scanner start was called */ public boolean wasStarted = false; /** * Flag for scanner stop was called */ public boolean wasStopped = false; /** * Method to access the private handler * * @return the internal handler */ public Handler getPrivateHandler() { return super.getHandler(); } /** * Method to access the private sample task as runnable * * @return the internal handler */ public Runnable getPrivateSampleTask() { return super.getTimerTask(); } /* * (non-Javadoc) * * @see * de.unikassel.android.sdcframework.devices.SampleTakingDeviceScanner#start * (android.content.Context) */ @Override public boolean start( Context context ) { wasStarted = true; return super.start( context ); } /* * (non-Javadoc) * * @see * de.unikassel.android.sdcframework.devices.SampleTakingDeviceScanner#stop * (android.content.Context) */ @Override public boolean stop( Context context ) { wasStopped = true; return super.stop( context ); } } /** * Test method for construction. */ public final void testSampleTakingDeviceScanner() { SampleTakingDeviceScannerForTest scanner = new SampleTakingDeviceScannerForTest(); assertNotNull( "Expected internal handler initialized on first access", scanner.getPrivateHandler() ); assertNotNull( "Expected internal task initialized on first access", scanner.getPrivateSampleTask() ); } /** * Test method for * {@link de.unikassel.android.sdcframework.devices.SampleTakingDeviceScanner#takeSample()} * . */ public final void testTakeSample() { // create scanner and device source SampleTakingDeviceScannerForTest scanner = new SampleTakingDeviceScannerForTest(); SampleProvidingSensorDeviceForTest device = new SampleProvidingSensorDeviceForTest( SensorDeviceIdentifier.GPS ); // add an event observer to the scanner SampleEventObserverForTest observer = new SampleEventObserverForTest(); scanner.registerEventObserver( observer ); try { device.currentSample = null; // first try for device null scanner.takeSample(); scanner.setDevice( device, getContext() ); // try for sample null scanner.takeSample(); // test for a valid preset sample Sample sample = TestSampleCollection.createSample( SensorDeviceIdentifier.GPS, TestGPSSampleData.createInitializedGPSSampleData() ); device.currentSample = sample; observer.observedEvents.clear(); scanner.takeSample(); assertEquals( "Expected one sample taken", 1, observer.observedEvents.size() ); assertSame( "Expected same sample", sample, observer.observedEvents.get( 0 ) ); } catch ( Exception e ) { e.printStackTrace(); fail( "Unexpected excpetion" ); } scanner.unregisterEventObserver( observer ); } /** * Test method for * {@link de.unikassel.android.sdcframework.devices.SampleTakingDeviceScanner#start(android.content.Context)} * and * {@link de.unikassel.android.sdcframework.devices.SampleTakingDeviceScanner#stop(android.content.Context)} * . */ public final void testStartAndStop() { final int scanFrequency = 200; final int sleepTime = 800; // create a device with samples with time stamp final SampleProvidingSensorDeviceForTest device = new SampleProvidingSensorDeviceForTest( SensorDeviceIdentifier.Unknown ); device.getConfiguration().setFrequency( scanFrequency ); device.getConfiguration().setEnabled( true ); device.doCreateSampleWithTimeStamp = true; // create a sample observer final SampleEventObserverForTest observer = new SampleEventObserverForTest(); /** * Internal looper test thread * * @author Katy Hilgenberg * */ class ScannerTestLooperThread extends LooperThreadForTest { /** * Our scanner under test */ public SampleTakingDeviceScannerForTest scanner = new SampleTakingDeviceScannerForTest(); /* * (non-Javadoc) * * @see * de.unikassel.android.sdcframework.devices.tests.LooperThreadForTest# * doPrepareTest() */ @Override public void doPrepareTest() { // create the scanner in the looper thread context to implicitly // associate handler with the threads looper scanner = new SampleTakingDeviceScannerForTest(); scanner.wasStarted = false; scanner.wasStopped = false; // add an event observer to the scanner scanner.registerEventObserver( observer ); // start scanner scanner.setDevice( device, getContext() ); // test if scanner was started as expected assertTrue( "Expected scanner running", scanner.isEnabled() ); assertTrue( "Expected scanner start called", scanner.wasStarted ); assertFalse( "Expected scanner stop not called", scanner.wasStopped ); } /** * Scanner stop test */ public void doStopScannerAndTest() { // stop scanner by setting the associated device to null scanner.wasStarted = false; scanner.wasStopped = false; scanner.setDevice( null, getContext() ); // test if scanner was stopped as expected assertFalse( "Expected scanner not running", scanner.isEnabled() ); assertFalse( "Expected scanner start not called", scanner.wasStarted ); assertTrue( "Expected scanner stop called", scanner.wasStopped ); } } ; // create a looper thread to test the handler based timing ScannerTestLooperThread looperThread = new ScannerTestLooperThread(); // start the looper thread and wait for PREPARATION finished looperThread.start(); while ( !looperThread.hasPreparationDone.get() ) { TestUtils.sleep( scanFrequency / 2 ); } TestUtils.sleep( sleepTime ); looperThread.doStopScannerAndTest(); // test for samples taken int sampleCount = observer.observedEvents.size(); assertTrue( "Expected more samples taken", sampleCount >= sleepTime / scanFrequency ); Sample lastSample = null; for ( Sample sample : observer.observedEvents ) { if ( lastSample != null ) { long timediff = sample.getTimeStamp() - lastSample.getTimeStamp(); // REMARK: due to bad emulator timing this is just a weak test assertTrue( "Unexpected sample frequency " + timediff, Math.abs( timediff - scanFrequency ) < scanFrequency ); } lastSample = sample; } // stop looper thread looperThread.interrupt(); } }