/*
* Catroid: An on-device visual programming system for Android devices
* Copyright (C) 2010-2016 The Catrobat Team
* (<http://developer.catrobat.org/credits>)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* An additional term exception under section 7 of the GNU Affero
* General Public License, version 3, is available at
* http://developer.catrobat.org/license_additional_term
*
* 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 Affero 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/>.
*/
package org.catrobat.catroid.uitest.bluetooth;
import android.content.Intent;
import android.widget.ListView;
import com.robotium.solo.Solo;
import org.catrobat.catroid.R;
import org.catrobat.catroid.bluetooth.ConnectBluetoothDeviceActivity;
import org.catrobat.catroid.bluetooth.base.BluetoothConnection;
import org.catrobat.catroid.bluetooth.base.BluetoothDevice;
import org.catrobat.catroid.bluetooth.base.BluetoothDeviceService;
import org.catrobat.catroid.common.CatroidService;
import org.catrobat.catroid.common.ServiceProvider;
import org.catrobat.catroid.common.bluetooth.BluetoothTestUtils;
import org.catrobat.catroid.common.bluetooth.ConnectionDataLogger;
import org.catrobat.catroid.uitest.annotation.Device;
import org.catrobat.catroid.uitest.util.BaseActivityInstrumentationTestCase;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.UUID;
public class BluetoothDeviceServiceTest extends BaseActivityInstrumentationTestCase<ConnectBluetoothDeviceActivity> {
public BluetoothDeviceServiceTest() {
super(ConnectBluetoothDeviceActivity.class, false);
}
private static final String PAIRED_UNAVAILABLE_DEVICE_NAME = "DUMMY DEVICE";
public static final Class<BluetoothTestDevice> TEST_DEVICE = BluetoothTestDevice.class;
private ConnectionDataLogger logger;
private Solo solo;
@Override
protected void setUp() throws Exception {
super.setUp();
Intent intent = new Intent(getInstrumentation().getContext(), CatroidService.BLUETOOTH_DEVICE_SERVICE);
intent.putExtra(ConnectBluetoothDeviceActivity.DEVICE_TO_CONNECT, TEST_DEVICE);
setActivityIntent(intent);
logger = ConnectionDataLogger.createBluetoothConnectionLoggerWithTestDevice(new BluetoothTestDevice());
BluetoothTestUtils.enableBluetooth();
solo = new Solo(getInstrumentation(), getActivity());
solo.unlockScreen();
}
@Override
protected void tearDown() throws Exception {
ServiceProvider.getService(CatroidService.BLUETOOTH_DEVICE_SERVICE).disconnectDevices();
logger.disconnectAndDestroy();
BluetoothTestUtils.disableBluetooth();
super.tearDown();
}
@Device
public void testBluetoothConnector() throws IOException {
solo.waitForActivity(ConnectBluetoothDeviceActivity.class);
ListView deviceList = solo.getCurrentViews(ListView.class).get(0);
String connectedDeviceName = (String) deviceList.getItemAtPosition(0);
assertFalse("No bluetooth device is paired, connection failed.",
connectedDeviceName == null || connectedDeviceName.equals(solo.getString(R.string.none_paired)));
solo.clickOnText(connectedDeviceName);
solo.sleep(5000); // wait for connection
BluetoothDeviceService btService = ServiceProvider.getService(CatroidService.BLUETOOTH_DEVICE_SERVICE);
BluetoothTestDevice btDevice = btService.getDevice(TEST_DEVICE);
assertNotNull("Device should be registered now. Bluetooth connection might failed. Is Bluetooth-Server running?", btDevice);
btDevice.connect();
byte[] expectedMessage = new byte[] { 1, 2, 3 };
btDevice.sendTestMessage(expectedMessage);
solo.sleep(2000); // wait some time till return message arrives
byte[] receivedMessage = btDevice.receiveTestMessage();
assertMessageEquals(expectedMessage, receivedMessage);
assertMessageEquals(expectedMessage, logger.getNextSentMessage(1));
assertMessageEquals(expectedMessage, logger.getNextReceivedMessage(1));
}
private void assertMessageEquals(byte[] expected, byte[] actual) {
assertEquals("Bluetooth message is not equal, because of different message length.", expected.length, actual.length);
for (int i = 0; i < expected.length; i++) {
assertEquals("Bluetooth message is not equal, byte " + i + " is different", expected[i], actual[i]);
}
}
@Device
public void testConnectNotAvailableBluetoothDevice() throws IOException {
solo.waitForActivity(ConnectBluetoothDeviceActivity.class);
BluetoothTestUtils.addPairedDevice(PAIRED_UNAVAILABLE_DEVICE_NAME, getActivity(), getInstrumentation());
ListView deviceList = solo.getCurrentViews(ListView.class).get(0);
String connectedDeviceName = null;
for (int i = 0; i < deviceList.getCount(); i++) {
String deviceName = (String) deviceList.getItemAtPosition(i);
if (deviceName.startsWith(PAIRED_UNAVAILABLE_DEVICE_NAME)) {
connectedDeviceName = deviceName;
break;
}
}
assertTrue("Bluetooth device '" + PAIRED_UNAVAILABLE_DEVICE_NAME + "' is not paired, so cannot connect.",
connectedDeviceName != null && solo.searchText(connectedDeviceName));
solo.clickOnText(connectedDeviceName);
solo.sleep(15000); //yes, has to be that long! waiting for connection timeout!
BluetoothDeviceService service = ServiceProvider.getService(CatroidService.BLUETOOTH_DEVICE_SERVICE);
assertNull("Device should not be registered, because test tries to connect to a device which is not available.",
service.getDevice(TEST_DEVICE));
}
private static class BluetoothTestDevice implements BluetoothDevice {
private static final UUID COMMON_BT_TEST_UUID = UUID.fromString("fd2835bb-9d80-41e0-9721-5372b90342da");
private boolean isConnected = false;
private BluetoothConnection connection;
private DataInputStream inStream;
private OutputStream outStream;
public boolean isConnected() {
return isConnected;
}
@Override
public String getName() {
return "BT Test Device";
}
@Override
public Class<? extends BluetoothDevice> getDeviceType() {
return BluetoothTestDevice.class;
}
@Override
public void setConnection(BluetoothConnection connection) {
this.connection = connection;
}
public void connect() throws IOException {
inStream = new DataInputStream(connection.getInputStream());
outStream = connection.getOutputStream();
isConnected = true;
}
@Override
public void disconnect() {
connection.disconnect();
isConnected = false;
}
@Override
public boolean isAlive() {
return isConnected;
}
@Override
public UUID getBluetoothDeviceUUID() {
return COMMON_BT_TEST_UUID;
}
public void sendTestMessage(byte[] message) throws IOException {
outStream.write(new byte[] { (byte) (0xFF & message.length) });
outStream.write(message);
outStream.flush();
}
public byte[] receiveTestMessage() throws IOException {
byte[] messageLengthBuffer = new byte[1];
inStream.readFully(messageLengthBuffer, 0, 1);
int expectedMessageLength = messageLengthBuffer[0];
byte[] payload = new byte[expectedMessageLength];
inStream.readFully(payload, 0, expectedMessageLength);
return payload;
}
@Override
public void initialise() {
}
@Override
public void start() {
}
@Override
public void pause() {
}
@Override
public void destroy() {
}
}
}