Skip to content

Commit

Permalink
Merge pull request #61 from clemarescx/bod_add_tests
Browse files Browse the repository at this point in the history
Add tests to BOD and fix parsing
  • Loading branch information
elpiel authored Oct 20, 2022
2 parents 500175e + acceca0 commit d5f1209
Showing 1 changed file with 83 additions and 12 deletions.
95 changes: 83 additions & 12 deletions src/sentences/bod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ use crate::{parse::*, sentences::utils::array_string, Error, SentenceType};

use arrayvec::ArrayString;
use nom::{
bytes::complete::take_until,
bytes::complete::{is_not, take_until},
character::complete::char,
combinator::{map_parser, opt},
number::complete::float,
sequence::preceded,
};

const MAX_LEN: usize = 64;
Expand Down Expand Up @@ -37,26 +38,21 @@ pub struct BodData {
fn do_parse_bod(i: &str) -> Result<BodData, Error> {
// 1. Bearing Degrees, True
let (i, bearing_true) = opt(map_parser(take_until(","), float))(i)?;
let (i, _) = char(',')(i)?;

// 2. T = True
let (i, _) = char('T')(i)?;
let (i, _) = char(',')(i)?;
let (i, _) = preceded(char(','), char('T'))(i)?;

// 3. Bearing Degrees, Magnetic
let (i, bearing_magnetic) = opt(float)(i)?;
let (i, _) = char(',')(i)?;
let (i, bearing_magnetic) = preceded(char(','), opt(float))(i)?;

// 4. M = Magnetic
let (i, _) = char('M')(i)?;
let (i, _) = char(',')(i)?;
let (i, _) = preceded(char(','), char('M'))(i)?;

// 5. Destination Waypoint
let (i, to_waypoint) = opt(take_until(","))(i)?;
let (i, _) = char(',')(i)?;
let (i, to_waypoint) = preceded(char(','), opt(is_not(",*")))(i)?;

// 6. origin Waypoint
let (_i, from_waypoint) = opt(take_until("*"))(i)?;
let from_waypoint = opt(preceded(char(','), is_not("*")))(i)?.1;

// 7. Checksum

Expand All @@ -78,6 +74,81 @@ pub fn parse_bod(sentence: NmeaSentence) -> Result<BodData, Error> {
found: sentence.message_id,
})
} else {
Ok(do_parse_bod(sentence.data)?)
do_parse_bod(sentence.data)
}
}

#[cfg(test)]
mod tests {

use approx::assert_relative_eq;

use super::*;

#[test]
fn parse_bod_with_route_active_example_full() {
let sentence = parse_nmea_sentence("$GPBOD,097.0,T,103.2,M,POINTB,POINTA*4A").unwrap();
assert_eq!(sentence.checksum, sentence.calc_checksum());
assert_eq!(sentence.checksum, 0x4A);

let data = parse_bod(sentence).unwrap();
assert_relative_eq!(data.bearing_true.unwrap(), 97.0);
assert_relative_eq!(data.bearing_magnetic.unwrap(), 103.2);
assert_eq!(data.to_waypoint.as_deref(), Some("POINTB"));
assert_eq!(data.from_waypoint.as_deref(), Some("POINTA"));
}

#[test]
fn parse_bod_with_route_active_missing_destination_waypoint_example_full() {
let sentence = parse_nmea_sentence("$GPBOD,097.0,T,103.2,M,,POINTA*44").unwrap();
assert_eq!(sentence.checksum, sentence.calc_checksum());
assert_eq!(sentence.checksum, 0x44);

let data = parse_bod(sentence).unwrap();
assert_relative_eq!(data.bearing_true.unwrap(), 97.0);
assert_relative_eq!(data.bearing_magnetic.unwrap(), 103.2);
assert!(data.to_waypoint.is_none());
assert_eq!(data.from_waypoint.as_deref(), Some("POINTA"));
}

#[test]
fn parse_bod_with_route_active_missing_source_waypoint_example_full() {
// this is equivalent to the "no route active" test, except here there is a comma with an empty field
// before the checksum. This is just to make sure parsing is resilient to missing data.
let sentence = parse_nmea_sentence("$GPBOD,097.0,T,103.2,M,POINTB,*47").unwrap();
assert_eq!(sentence.checksum, sentence.calc_checksum());
assert_eq!(sentence.checksum, 0x47);

let data = parse_bod(sentence).unwrap();
assert_relative_eq!(data.bearing_true.unwrap(), 97.0);
assert_relative_eq!(data.bearing_magnetic.unwrap(), 103.2);
assert_eq!(data.to_waypoint.as_deref(), Some("POINTB"));
assert!(data.from_waypoint.is_none());
}

#[test]
fn parse_bod_no_route_active_example_full() {
let sentence = parse_nmea_sentence("$GPBOD,099.3,T,105.6,M,POINTB*64").unwrap();
assert_eq!(sentence.checksum, sentence.calc_checksum());
assert_eq!(sentence.checksum, 0x64);
let data = parse_bod(sentence).unwrap();

assert_relative_eq!(data.bearing_true.unwrap(), 99.3);
assert_relative_eq!(data.bearing_magnetic.unwrap(), 105.6);
assert_eq!(data.to_waypoint.as_deref(), Some("POINTB"));
assert!(data.from_waypoint.is_none());
}

#[test]
fn parse_bod_no_route_active_no_bearing_example_full() {
let sentence = parse_nmea_sentence("$GPBOD,,T,105.6,M,POINTB*49").unwrap();
assert_eq!(sentence.checksum, sentence.calc_checksum());
assert_eq!(sentence.checksum, 0x49);
let data = parse_bod(sentence).unwrap();

assert!(data.bearing_true.is_none());
assert_relative_eq!(data.bearing_magnetic.unwrap(), 105.6);
assert_eq!(data.to_waypoint.as_deref(), Some("POINTB"));
assert!(data.from_waypoint.is_none());
}
}

0 comments on commit d5f1209

Please sign in to comment.