452 lines
17 KiB
Java
452 lines
17 KiB
Java
/* Copyright (C) 2022-2023 Martin.JM
|
|
|
|
This file is part of Gadgetbridge.
|
|
|
|
Gadgetbridge 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.
|
|
|
|
Gadgetbridge 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 nodomain.freeyourgadget.gadgetbridge.service.devices.huawei;
|
|
|
|
import static org.mockito.Matchers.any;
|
|
import static org.mockito.Mockito.times;
|
|
import static org.mockito.Mockito.verify;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
import android.bluetooth.BluetoothGattCharacteristic;
|
|
import android.content.Context;
|
|
|
|
import org.junit.Assert;
|
|
import org.junit.Before;
|
|
import org.junit.Test;
|
|
import org.junit.runner.RunWith;
|
|
import org.mockito.Mockito;
|
|
import org.mockito.runners.MockitoJUnitRunner;
|
|
|
|
import java.io.IOException;
|
|
import java.lang.reflect.Field;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.UUID;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
|
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.HuaweiPacket;
|
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.Workout;
|
|
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
|
import nodomain.freeyourgadget.gadgetbridge.service.btbr.Transaction;
|
|
import nodomain.freeyourgadget.gadgetbridge.service.btbr.TransactionBuilder;
|
|
import nodomain.freeyourgadget.gadgetbridge.service.devices.huawei.requests.Request;
|
|
|
|
@RunWith(MockitoJUnitRunner.class)
|
|
public class TestResponseManager {
|
|
|
|
HuaweiSupportProvider supportProvider = new HuaweiSupportProvider(new HuaweiLESupport()) {
|
|
|
|
@Override
|
|
public boolean isBLE() {
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public Context getContext() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public GBDevice getDevice() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public byte[] getSerial() {
|
|
return new byte[0];
|
|
}
|
|
|
|
@Override
|
|
public String getDeviceMac() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public byte[] getMacAddress() {
|
|
return new byte[0];
|
|
}
|
|
|
|
@Override
|
|
public byte[] getAndroidId() {
|
|
return new byte[0];
|
|
}
|
|
|
|
@Override
|
|
public short getNotificationId() {
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public TransactionBuilder createBrTransactionBuilder(String taskName) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder createLeTransactionBuilder(String taskName) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void performConnected(Transaction transaction) throws IOException {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void performConnected(nodomain.freeyourgadget.gadgetbridge.service.btle.Transaction transaction) throws IOException {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void evaluateGBDeviceEvent(GBDeviceEvent deviceEvent) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public BluetoothGattCharacteristic getLeCharacteristic(UUID uuid) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public HuaweiPacket.ParamsProvider getParamsProvider() {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void addInProgressRequest(Request request) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void removeInProgressRequests(Request request) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void setSecretKey(byte[] authKey) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public byte[] getSecretKey() {
|
|
return new byte[0];
|
|
}
|
|
|
|
@Override
|
|
public void addTotalFitnessData(int steps, int calories, int distance) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void addSleepActivity(int timestamp, short duration, byte type) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void addStepData(int timestamp, short steps, short calories, short distance, byte spo, byte heartrate) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public Long addWorkoutTotalsData(Workout.WorkoutTotals.Response packet) {
|
|
return null;
|
|
}
|
|
|
|
@Override
|
|
public void addWorkoutSampleData(Long workoutId, List<Workout.WorkoutData.Response.Data> dataList) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void addWorkoutPaceData(Long workoutId, List<Workout.WorkoutPace.Response.Block> paceList) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void sendSetMusic() {
|
|
|
|
}
|
|
};
|
|
|
|
Field handlersField;
|
|
Field receivedPacketField;
|
|
Field asynchronousResponseField;
|
|
|
|
@Before
|
|
public void beforeClass() throws NoSuchFieldException {
|
|
handlersField = ResponseManager.class.getDeclaredField("handlers");
|
|
handlersField.setAccessible(true);
|
|
|
|
asynchronousResponseField = ResponseManager.class.getDeclaredField("asynchronousResponse");
|
|
asynchronousResponseField.setAccessible(true);
|
|
|
|
receivedPacketField = ResponseManager.class.getDeclaredField("receivedPacket");
|
|
receivedPacketField.setAccessible(true);
|
|
}
|
|
|
|
@Test
|
|
public void testAddHandler() throws IllegalAccessException {
|
|
Request input = new Request(supportProvider);
|
|
|
|
List<Request> expectedHandlers = Collections.synchronizedList(new ArrayList<Request>());
|
|
expectedHandlers.add(input);
|
|
|
|
ResponseManager responseManager = new ResponseManager(supportProvider);
|
|
responseManager.addHandler(input);
|
|
|
|
Assert.assertEquals(expectedHandlers, handlersField.get(responseManager));
|
|
}
|
|
|
|
@Test
|
|
public void testRemoveHandler() throws IllegalAccessException {
|
|
Request input = new Request(supportProvider);
|
|
Request extra = new Request(supportProvider);
|
|
|
|
List<Request> inputHandlers = Collections.synchronizedList(new ArrayList<Request>());
|
|
inputHandlers.add(extra);
|
|
inputHandlers.add(input);
|
|
inputHandlers.add(extra);
|
|
|
|
List<Request> expectedHandlers = Collections.synchronizedList(new ArrayList<Request>());
|
|
expectedHandlers.add(extra);
|
|
expectedHandlers.add(extra);
|
|
|
|
ResponseManager responseManager = new ResponseManager(supportProvider);
|
|
handlersField.set(responseManager, inputHandlers);
|
|
|
|
responseManager.removeHandler(input);
|
|
|
|
Assert.assertEquals(expectedHandlers, handlersField.get(responseManager));
|
|
}
|
|
|
|
@Test
|
|
public void testHandleDataCompletePacketSynchronous() throws Exception {
|
|
// Note that this is not a proper packet, but that doesn't matter as we're not testing
|
|
// the packet parsing.
|
|
byte[] input = {0x01, 0x02, 0x03, 0x04};
|
|
|
|
AsynchronousResponse mockAsynchronousResponse = Mockito.mock(AsynchronousResponse.class);
|
|
|
|
HuaweiPacket mockHuaweiPacket = Mockito.mock(HuaweiPacket.class);
|
|
mockHuaweiPacket.complete = true;
|
|
when(mockHuaweiPacket.parse((byte[]) any()))
|
|
.thenReturn(mockHuaweiPacket);
|
|
|
|
Request request1 = Mockito.mock(Request.class);
|
|
when(request1.handleResponse((HuaweiPacket) any()))
|
|
.thenReturn(true);
|
|
Request request2 = Mockito.mock(Request.class);
|
|
// FIXME: Removed due to UnnecessaryStubbingException after mockito-core update
|
|
//when(request2.handleResponse((HuaweiPacket) any()))
|
|
// .thenReturn(false);
|
|
|
|
List<Request> inputHandlers = Collections.synchronizedList(new ArrayList<Request>());
|
|
inputHandlers.add(request1);
|
|
inputHandlers.add(request2);
|
|
|
|
List<Request> expectedHandlers = Collections.synchronizedList(new ArrayList<Request>());
|
|
expectedHandlers.add(request2);
|
|
|
|
ResponseManager responseManager = new ResponseManager(supportProvider);
|
|
handlersField.set(responseManager, inputHandlers);
|
|
receivedPacketField.set(responseManager, mockHuaweiPacket);
|
|
asynchronousResponseField.set(responseManager, mockAsynchronousResponse);
|
|
|
|
responseManager.handleData(input);
|
|
|
|
Assert.assertEquals(expectedHandlers, handlersField.get(responseManager));
|
|
Assert.assertNull(receivedPacketField.get(responseManager));
|
|
|
|
verify(mockHuaweiPacket, times(1)).parse(input);
|
|
verify(mockAsynchronousResponse, times(0)).handleResponse((HuaweiPacket) any());
|
|
verify(request1, times(1)).handleResponse(mockHuaweiPacket);
|
|
verify(request1, times(1)).handleResponse();
|
|
verify(request2, times(0)).handleResponse((HuaweiPacket) any());
|
|
verify(request2, times(0)).handleResponse();
|
|
}
|
|
|
|
@Test
|
|
public void testHandleDataCompletePacketAsynchronous() throws Exception {
|
|
// Note that this is not a proper packet, but that doesn't matter as we're not testing
|
|
// the packet parsing.
|
|
byte[] input = {0x01, 0x02, 0x03, 0x04};
|
|
|
|
AsynchronousResponse mockAsynchronousResponse = Mockito.mock(AsynchronousResponse.class);
|
|
|
|
HuaweiPacket mockHuaweiPacket = Mockito.mock(HuaweiPacket.class);
|
|
mockHuaweiPacket.complete = true;
|
|
when(mockHuaweiPacket.parse((byte[]) any()))
|
|
.thenReturn(mockHuaweiPacket);
|
|
|
|
Request request1 = Mockito.mock(Request.class);
|
|
when(request1.handleResponse((HuaweiPacket) any()))
|
|
.thenReturn(false);
|
|
Request request2 = Mockito.mock(Request.class);
|
|
when(request2.handleResponse((HuaweiPacket) any()))
|
|
.thenReturn(false);
|
|
|
|
List<Request> inputHandlers = Collections.synchronizedList(new ArrayList<Request>());
|
|
inputHandlers.add(request1);
|
|
inputHandlers.add(request2);
|
|
|
|
List<Request> expectedHandlers = Collections.synchronizedList(new ArrayList<Request>());
|
|
expectedHandlers.add(request1);
|
|
expectedHandlers.add(request2);
|
|
|
|
ResponseManager responseManager = new ResponseManager(supportProvider);
|
|
handlersField.set(responseManager, inputHandlers);
|
|
receivedPacketField.set(responseManager, mockHuaweiPacket);
|
|
asynchronousResponseField.set(responseManager, mockAsynchronousResponse);
|
|
|
|
responseManager.handleData(input);
|
|
|
|
Assert.assertEquals(expectedHandlers, handlersField.get(responseManager));
|
|
Assert.assertNull(receivedPacketField.get(responseManager));
|
|
|
|
verify(mockHuaweiPacket, times(1)).parse(input);
|
|
verify(mockAsynchronousResponse, times(1)).handleResponse(mockHuaweiPacket);
|
|
verify(request1, times(1)).handleResponse(mockHuaweiPacket);
|
|
verify(request1, times(0)).handleResponse();
|
|
verify(request2, times(1)).handleResponse(mockHuaweiPacket);
|
|
verify(request2, times(0)).handleResponse();
|
|
}
|
|
|
|
@Test
|
|
public void testHandleDataTwoPartialPacketsSynchronous() throws Exception {
|
|
// Note that this is not a proper packet, but that doesn't matter as we're not testing
|
|
// the packet parsing.
|
|
byte[] input1 = {0x01, 0x02, 0x03, 0x04};
|
|
byte[] input2 = {0x05, 0x06, 0x07, 0x08};
|
|
|
|
AsynchronousResponse mockAsynchronousResponse = Mockito.mock(AsynchronousResponse.class);
|
|
|
|
HuaweiPacket mockHuaweiPacket = Mockito.mock(HuaweiPacket.class);
|
|
mockHuaweiPacket.complete = false;
|
|
when(mockHuaweiPacket.parse((byte[]) any()))
|
|
.thenReturn(mockHuaweiPacket);
|
|
|
|
Request request1 = Mockito.mock(Request.class);
|
|
when(request1.handleResponse((HuaweiPacket) any()))
|
|
.thenReturn(true);
|
|
Request request2 = Mockito.mock(Request.class);
|
|
// FIXME: Removed due to UnnecessaryStubbingException after mockito-core update
|
|
//when(request2.handleResponse((HuaweiPacket) any()))
|
|
// .thenReturn(false);
|
|
|
|
List<Request> inputHandlers = Collections.synchronizedList(new ArrayList<Request>());
|
|
inputHandlers.add(request1);
|
|
inputHandlers.add(request2);
|
|
|
|
List<Request> expectedHandlers1 = Collections.synchronizedList(new ArrayList<Request>());
|
|
expectedHandlers1.add(request1);
|
|
expectedHandlers1.add(request2);
|
|
|
|
List<Request> expectedHandlers2 = Collections.synchronizedList(new ArrayList<Request>());
|
|
expectedHandlers2.add(request2);
|
|
|
|
ResponseManager responseManager = new ResponseManager(supportProvider);
|
|
handlersField.set(responseManager, inputHandlers);
|
|
receivedPacketField.set(responseManager, mockHuaweiPacket);
|
|
asynchronousResponseField.set(responseManager, mockAsynchronousResponse);
|
|
|
|
responseManager.handleData(input1);
|
|
|
|
Assert.assertEquals(expectedHandlers1, handlersField.get(responseManager));
|
|
Assert.assertEquals(mockHuaweiPacket, receivedPacketField.get(responseManager));
|
|
|
|
verify(mockHuaweiPacket, times(1)).parse(input1);
|
|
verify(mockAsynchronousResponse, times(0)).handleResponse((HuaweiPacket) any());
|
|
verify(request1, times(0)).handleResponse(mockHuaweiPacket);
|
|
verify(request1, times(0)).handleResponse();
|
|
verify(request2, times(0)).handleResponse((HuaweiPacket) any());
|
|
verify(request2, times(0)).handleResponse();
|
|
|
|
mockHuaweiPacket.complete = true;
|
|
responseManager.handleData(input2);
|
|
|
|
Assert.assertEquals(expectedHandlers2, handlersField.get(responseManager));
|
|
Assert.assertNull(receivedPacketField.get(responseManager));
|
|
|
|
verify(mockHuaweiPacket, times(1)).parse(input2);
|
|
verify(mockAsynchronousResponse, times(0)).handleResponse((HuaweiPacket) any());
|
|
verify(request1, times(1)).handleResponse(mockHuaweiPacket);
|
|
verify(request1, times(1)).handleResponse();
|
|
verify(request2, times(0)).handleResponse((HuaweiPacket) any());
|
|
verify(request2, times(0)).handleResponse();
|
|
}
|
|
|
|
@Test
|
|
public void testHandleDataTwoPartialPacketsAsynchronous() throws Exception {
|
|
// Note that this is not a proper packet, but that doesn't matter as we're not testing
|
|
// the packet parsing.
|
|
byte[] input1 = {0x01, 0x02, 0x03, 0x04};
|
|
byte[] input2 = {0x05, 0x06, 0x07, 0x08};
|
|
|
|
AsynchronousResponse mockAsynchronousResponse = Mockito.mock(AsynchronousResponse.class);
|
|
|
|
HuaweiPacket mockHuaweiPacket = Mockito.mock(HuaweiPacket.class);
|
|
mockHuaweiPacket.complete = false;
|
|
when(mockHuaweiPacket.parse((byte[]) any()))
|
|
.thenReturn(mockHuaweiPacket);
|
|
|
|
Request request1 = Mockito.mock(Request.class);
|
|
when(request1.handleResponse((HuaweiPacket) any()))
|
|
.thenReturn(false);
|
|
Request request2 = Mockito.mock(Request.class);
|
|
when(request2.handleResponse((HuaweiPacket) any()))
|
|
.thenReturn(false);
|
|
|
|
List<Request> inputHandlers = Collections.synchronizedList(new ArrayList<Request>());
|
|
inputHandlers.add(request1);
|
|
inputHandlers.add(request2);
|
|
|
|
List<Request> expectedHandlers = Collections.synchronizedList(new ArrayList<Request>());
|
|
expectedHandlers.add(request1);
|
|
expectedHandlers.add(request2);
|
|
|
|
ResponseManager responseManager = new ResponseManager(supportProvider);
|
|
handlersField.set(responseManager, inputHandlers);
|
|
receivedPacketField.set(responseManager, mockHuaweiPacket);
|
|
asynchronousResponseField.set(responseManager, mockAsynchronousResponse);
|
|
|
|
responseManager.handleData(input1);
|
|
|
|
Assert.assertEquals(expectedHandlers, handlersField.get(responseManager));
|
|
Assert.assertEquals(mockHuaweiPacket, receivedPacketField.get(responseManager));
|
|
|
|
verify(mockHuaweiPacket, times(1)).parse(input1);
|
|
verify(mockAsynchronousResponse, times(0)).handleResponse((HuaweiPacket) any());
|
|
verify(request1, times(0)).handleResponse(mockHuaweiPacket);
|
|
verify(request1, times(0)).handleResponse();
|
|
verify(request2, times(0)).handleResponse((HuaweiPacket) any());
|
|
verify(request2, times(0)).handleResponse();
|
|
|
|
mockHuaweiPacket.complete = true;
|
|
responseManager.handleData(input2);
|
|
|
|
Assert.assertEquals(expectedHandlers, handlersField.get(responseManager));
|
|
Assert.assertNull(receivedPacketField.get(responseManager));
|
|
|
|
verify(mockHuaweiPacket, times(1)).parse(input2);
|
|
verify(mockAsynchronousResponse, times(1)).handleResponse((HuaweiPacket) any());
|
|
verify(request1, times(1)).handleResponse(mockHuaweiPacket);
|
|
verify(request1, times(0)).handleResponse();
|
|
verify(request2, times(1)).handleResponse((HuaweiPacket) any());
|
|
verify(request2, times(0)).handleResponse();
|
|
}
|
|
}
|