package com.roboclub.robobuggy.nodes.sensors;
import com.roboclub.robobuggy.messages.GpsMeasurement;
import com.roboclub.robobuggy.ros.Message;
import com.roboclub.robobuggy.ros.MessageListener;
import com.roboclub.robobuggy.ros.NodeChannel;
import com.roboclub.robobuggy.ros.Subscriber;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.nio.charset.Charset;
import java.util.Date;
import java.util.concurrent.LinkedBlockingQueue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
/**
* Created by abhinavgirish on 9/30/16.
*/
public class GpsNodeTest {
private static LinkedBlockingQueue<GpsMeasurement> messageList = new LinkedBlockingQueue<>();
/**
* Called before any tests run, and only called once
*
* Sets up the subscriber catcher into the message list
*/
@BeforeClass
public static void oneTimeSetup() {
new Subscriber("gpsLoc", NodeChannel.GPS.getMsgPath(), new MessageListener() {
@Override
public void actionPerformed(String topicName, Message m) {
messageList.add((GpsMeasurement) m);
}
});
}
/**
* Called before each test case runs
*
* Clears the message list so we don't get any corruption between tests
*/
@Before
public void setUp() {
messageList.clear();
}
/**
* Called after each test case finishes
*
* Does nothing at the moment
*/
@After
public void tearDown() {
}
/**
* tests that message is properly parsed for a legitimate input
*/
@Test
public void testStandardGPSNode()
{
// to do - move subscriber stuff to oneTimeSetup(), call peel with the sample input, let it sleep for a
// seconds, then check the LinkedBlockingQueue for messages
GpsNode gpsNode1 = new GpsNode(NodeChannel.GPS, "");
//testing peel
String input = "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47";
byte[] bytes = Charset.forName("UTF-8").encode(input).array();
gpsNode1.peel(bytes,0,bytes.length);
try {
Thread.sleep(3000);
if (messageList.size() != 1) {
fail("Did not receive message");
}
while (!messageList.isEmpty()) {
GpsMeasurement m = messageList.take();
assertEquals(m.getLatitude(), 48.1173, 0.0);
assertEquals(m.getLongitude(), 11.51667, 0.0001);
assertEquals(m.getNorth(), true);
assertEquals(m.getWest(), false);
}
}
catch (InterruptedException e){
fail("thread interrupted");
}
}
/**
* tests for correct failure if given longitude with invalid character
*/
@Test
public void testBadLong()
{
GpsNode gpsNode1 = new GpsNode(NodeChannel.GPS,"buggy");
String input = "$GPGGA,123519,4807.038,N,011A1.000,E,1,08,0.9,545.4,M,46.9,M,,*47";
byte[] bytes = Charset.forName("UTF-8").encode(input).array();
try {
gpsNode1.peel(bytes,0,bytes.length);
fail("This shouldn't parse longitude");
}
catch (NumberFormatException e){
return;
}
}
/**
* tests for correct failure if given latitude with invalid character
*/
@Test
public void testBadLat()
{
GpsNode gpsNode1 = new GpsNode(NodeChannel.GPS,"buggy");
String input = "$GPGGA,123519,48I7.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47";
byte[] bytes = Charset.forName("UTF-8").encode(input).array();
try {
gpsNode1.peel(bytes,0,bytes.length);
fail("This shouldn't parse latitude");
}
catch (NumberFormatException e){
return;
}
}
/**
* tests for correct failure if given latitude and longitude with invalid characters
*/
@Test
public void testBadLatAndLong()
{
GpsNode gpsNode1 = new GpsNode(NodeChannel.GPS,"buggy");
String input = "$GPGGA,123519,48I7.038,N,011R1.000,E,1,08,0.9,545.4,M,46.9,M,,*47";
byte[] bytes = Charset.forName("UTF-8").encode(input).array();
try {
gpsNode1.peel(bytes,0,bytes.length);
fail("This shouldn't parse latitude and longitude");
}
catch (NumberFormatException e){
return;
}
}
/**
* tests if convertHHMMSStoTime() method works correctly on valid input
*/
@Test
public void testConversionDateTime(){
GpsNode gpsNode1 = new GpsNode(NodeChannel.GPS,"buggy");
String input = "123519";
Date d1 = gpsNode1.convertHHMMSStoTime(input);
assertEquals(d1.getHours(),12);
assertEquals(d1.getMinutes(),35);
assertEquals(d1.getSeconds(),19);
//posDDMMmmmm could correspond to a reading of 41d 24.8963' N
}
/**
* tests if convertHHMMSStoTime() method works correctly on valid input
*/
@Test
public void testBadConversionDateTime(){
GpsNode gpsNode1 = new GpsNode(NodeChannel.GPS,"buggy");
String input = "123L19";
try {
Date d1 = gpsNode1.convertHHMMSStoTime(input);
fail("could not convert the time");
} catch (AssertionError e){
return;
}
}
/**
* tests if convertMinutesSecondsToFloat() works correctly on valid input
*/
@Test
public void testConversionMinSecToFloat()
{
GpsNode gpsNode1 = new GpsNode(NodeChannel.GPS,"buggy");
String input = "4807.038";
double output = gpsNode1.convertMinutesSecondsToFloat(input);
assertEquals(output,48.1173,0.001);
}
/**
* tests for correct failure if convertMinutesSecondsToFloat() is given invalid input
*/
@Test
public void testBadConversionMinSecToFloat()
{
GpsNode gpsNode1 = new GpsNode(NodeChannel.GPS,"buggy");
String input = "480O.038";
try {
double output = gpsNode1.convertMinutesSecondsToFloat(input);
fail("cannot convert given latitude");
} catch (NumberFormatException e){
return;
}
}
/**
* tests if convertMinSecToFloatLongitude() works correctly on valid input
*/
@Test
public void testConversionMinSecToFloatLong()
{
GpsNode gpsNode1 = new GpsNode(NodeChannel.GPS,"buggy");
String input = "01131.000";
double output = gpsNode1.convertMinSecToFloatLongitude(input);
assertEquals(output,11.5167,0.001);
}
/**
* tests for correct failure of convertMinSecToFloatLongitude()
* if given invalid input
*/
@Test
public void testBadConversionMinSecToFloatLong()
{
GpsNode gpsNode1 = new GpsNode(NodeChannel.GPS,"buggy");
String input = "01E31.000";
try
{
double output = gpsNode1.convertMinSecToFloatLongitude(input);
fail("couldn't convert longitude - invalid input");
} catch (NumberFormatException e){
return;
}
}
}