/*
* cameracontrol
* Copyright (C) 2010 Stefano Fornari
*
* This program is free software; you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License version 3 as published by
* the Free Software Foundation with the addition of the following permission
* added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
* WORK IN WHICH THE COPYRIGHT IS OWNED BY Stefano Fornari, Stefano Fornari
* DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
*
* 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 Affero General Public License
* along with this program; if not, see http://www.gnu.org/licenses or write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA.
*/
package ste.cameracontrol;
import ch.ntb.usb.LibusbJava;
import ch.ntb.usb.devinf.CanonEOS1000D;
import java.io.File;
import java.lang.reflect.Method;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.commons.io.IOUtils;
import ste.cameracontrol.event.ConnectedEventListener;
import ste.ptp.PTPException;
import ste.ptp.Response;
import ste.ptp.eos.EosEvent;
import ste.ptp.eos.EosInitiator;
/**
* Unit test for simple App.
*/
public class CameraControllerTest
extends TestCase {
public final String IMAGE_DIR = "/tmp/cameracontrol";
public final String IMAGE_NAME = "capture";
public final String IMAGE_NAME_JPG = IMAGE_NAME + ".JPG";
public final String IMAGE_NAME_CR2 = IMAGE_NAME + ".CR2";
private CameraController CONTROLLER = null;
private Configuration CONFIG = null;
/**
* Create the test case
*
* @param testName name of the test case
*/
public CameraControllerTest(String testName) {
super(testName);
}
/**
* @return the suite of tests being tested
*/
public static Test suite() {
return new TestSuite(CameraControllerTest.class);
}
@Override
protected void setUp() throws Exception {
super.setUp();
EosInitiator.shootError = false;
EosInitiator.invoked.clear();
EosInitiator.events.clear();
File outDir = new File(IMAGE_DIR);
if (!outDir.exists()) {
outDir.mkdirs();
} else {
String[] files = outDir.list();
for (int i=0; (files != null) && (i<files.length); ++i) {
(new File(outDir, files[i])).delete();
}
}
CONFIG = new Configuration();
CONFIG.setImageDir(IMAGE_DIR);
CONTROLLER = CameraController.getInstance();
CONTROLLER.initialize(CONFIG);
new File(IMAGE_DIR, IMAGE_NAME_JPG).delete();
new File(IMAGE_DIR, IMAGE_NAME_CR2).delete();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
File outDir = new File(IMAGE_DIR);
if (outDir.exists()) {
String[] files = outDir.list();
for (int i=0; (files != null) && (i<files.length); ++i) {
(new File(outDir, files[i])).delete();
}
outDir.delete();
}
}
private void fireCameraConnectionEvent() throws Exception {
Method m = CONTROLLER.getClass().getDeclaredMethod("setConnected");
m.setAccessible(true);
m.invoke(CONTROLLER);
}
private void setCameraStatus(boolean connected) throws Exception {
LibusbJava.init(new CanonEOS1000D(connected));
CONTROLLER.initialize();
}
private void setCameraStatus(boolean connected, Configuration c) throws Exception {
LibusbJava.init(new CanonEOS1000D(connected));
CONTROLLER.initialize(c);
}
public void testSingleton() throws Exception {
CameraController c1 = CameraController.getInstance();
CameraController c2 = CameraController.getInstance();
assertNotNull(c1);
assertSame(c1, c2);
}
public void testCameraIsConnected() throws Exception {
setCameraStatus(true);
assertTrue(CONTROLLER.isConnected());
}
public void testCameraIsNotConnected() throws Exception {
setCameraStatus(false);
assertFalse(CONTROLLER.isConnected());
}
public void testNoFireConnectionEvent() throws Exception {
setCameraStatus(true);
fireCameraConnectionEvent();
//
// We should have no errors
//
}
public void testInitializeWithConfiguration() {
Configuration c = CONTROLLER.getConfiguration();
assertEquals(IMAGE_DIR, c.getImageDir());
}
public void testInitializeWithWrongConfiguration() {
try {
CONTROLLER.initialize(null);
fail("the configuration object cannot be null");
} catch (IllegalArgumentException e) {
//
// OK!
//
}
}
/**
* This methods tests that when the camera disconnects and reconnects, the
* controller properly re-initialize it-self so to reflect that no camera is
* connected.
*
* @throws Exception
*/
public void testDeviceConnectAndDisconnect() throws Exception {
setCameraStatus(true);
CONTROLLER.startCamera();
LibusbJava.init(new CanonEOS1000D(false));
try {
CONTROLLER.startCamera();
fail("sanity check should fail at this point!");
} catch (PTPException e) {
//
// Expected behaviour
//
}
LibusbJava.init(new CanonEOS1000D(true));
CONTROLLER.startCamera();
}
public void testFireConnectionEvent() throws Exception {
setCameraStatus(true);
ConnectedEventListener[] listeners = {
new ConnectedEventListener(),
new ConnectedEventListener()
};
for (ConnectedEventListener l: listeners) {
CONTROLLER.addCameraListener(l);
}
fireCameraConnectionEvent();
for (ConnectedEventListener l: listeners) {
assertNotNull(l.device);
}
}
public void testStartCameraMonitor() throws Exception {
setCameraStatus(false);
ConnectedEventListener l = new ConnectedEventListener();
CONTROLLER.addCameraListener(l);
CONTROLLER.startCameraMonitor();
Thread.sleep(100);
assertNull(l.device);
LibusbJava.init(new CanonEOS1000D(true));
Thread.sleep(100);
assertNotNull(l.device);
//
// It has to notify only changes
//
l.device = null;
Thread.sleep(100);
assertNull(l.device);
}
public void testStopCameraMonitor() throws Exception {
setCameraStatus(true);
ConnectedEventListener l = new ConnectedEventListener();
//
// By default the monitor does not run
//
CONTROLLER.addCameraListener(l);
Thread.sleep(100);
assertNull(l.device);
//
// Let's start the monitor now
//
l.device = null;
CONTROLLER.startCameraMonitor();
Thread.sleep(100);
assertNotNull(l.device);
//
// Let's stop the monitor and detach the camera
//
l.device = null;
LibusbJava.init(new CanonEOS1000D(false));
CONTROLLER.stopCameraMonior();
Thread.sleep(100);
assertNull(l.device);
}
public void testDetectValidDevice() throws Exception {
CanonEOS1000D devinfo = new CanonEOS1000D(true);
LibusbJava.init(devinfo);
CONTROLLER.initialize();
ConnectedEventListener l = new ConnectedEventListener();
CONTROLLER.addCameraListener(l);
fireCameraConnectionEvent();
assertEquals(devinfo.getVendorId(), l.device.getVendorId());
assertEquals(devinfo.getProductId(), l.device.getProductId());
}
public void testShootOK() throws Exception {
CONTROLLER.startCamera();
CONTROLLER.shoot();
assertTrue(EosInitiator.invoked.contains("initiateCapture"));
}
public void testShootKO() throws Exception {
EosInitiator.shootError = true;
try {
CONTROLLER.startCamera();
CONTROLLER.shoot();
fail("Error not thrown");
} catch (PTPException e) {
assertEquals(Response.GeneralError, e.getErrorCode());
}
}
public void testDownloadPhoto() throws Exception {
CONTROLLER.startCamera();
Photo photo = new Photo(IMAGE_NAME);
CONTROLLER.downloadPhoto(1, 256, photo, false);
assertTrue(EosInitiator.invoked.contains("getPartialObject"));
assertTrue(EosInitiator.invoked.contains("transferComplete"));
assertNotNull(photo);
assertEquals(IMAGE_NAME, photo.getName());
assertTrue(photo.hasJpeg());
assertFalse(photo.hasRaw());
CONTROLLER.downloadPhoto(1, 256, photo, true);
assertTrue(photo.hasRaw());
}
public void testShootAndSave() throws Exception {
EosEvent photo1 = new EosEvent();
EosEvent photo2 = new EosEvent();
photo1.setCode(EosEvent.EosEventObjectAddedEx);
photo2.setCode(EosEvent.EosEventObjectAddedEx);
photo1.setParam(1, 1); photo2.setParam(1, 1);
photo1.setParam(5, 256); photo2.setParam(5, 256);
photo1.setParam(6, IMAGE_NAME_JPG); photo2.setParam(6, IMAGE_NAME_CR2);
EosInitiator.events.add(photo1); EosInitiator.events.add(photo2);
CONTROLLER.startCamera();
Photo[] photos = CONTROLLER.shootAndDownload();
assertTrue(EosInitiator.invoked.contains("initiateCapture"));
assertEquals(1, photos.length);
assertEquals(IMAGE_NAME, photos[0].getName());
assertNotNull(photos[0].getJpegData());
assertNotNull(photos[0].getRawData());
}
public void testSavePhoto() throws Exception {
Photo photo = new Photo(IMAGE_NAME);
File fjpg = new File(IMAGE_DIR, IMAGE_NAME_JPG);
File fraw = new File(IMAGE_DIR, IMAGE_NAME_CR2);
CONTROLLER.savePhoto(photo);
assertFalse(fjpg.exists());
assertFalse(fraw.exists());
photo.setJpegData(new byte[] {32});
CONTROLLER.savePhoto(photo);
assertTrue(fjpg.exists());
assertEquals(1, fjpg.length());
assertFalse(fraw.exists());
photo.setJpegData(new byte[] {32, 64});
photo.setRawData(new byte[] {32, 64});
CONTROLLER.savePhoto(photo);
assertEquals(2, fjpg.length());
assertTrue(fraw.exists());
assertEquals(2, fraw.length());
}
}