use std::{ error::Error, fs::{self, File}, io::{BufRead, BufReader}, path::Path, }; use helpers::format_satellites; use nmea::{parse_str, Nmea}; mod helpers; #[test] fn test_parse_file_log() { let res = process_file(&Path::new("tests").join("data").join("nmea1.log")) .unwrap_or_else(|err| panic!("process file failed with error '{}'", err)); let expected: Vec<_> = BufReader::new( File::open(Path::new("tests").join("data").join("nmea1.log.expected")).unwrap(), ) .lines() .collect::>() .expect("Should collect lines"); assert_eq!(expected, res); } #[test] fn test_parse_issue_2() { let mut input = BufReader::new(File::open(Path::new("tests").join("data").join("nmea2.log")).unwrap()); let mut nmea = Nmea::default(); for _ in 0..100 { let mut buffer = String::new(); let size = input.read_line(&mut buffer).unwrap(); eprintln!("buffer = {:?}", buffer); if size > 0 { if buffer.as_bytes()[0] == b'$' { let _ = nmea.parse(&buffer); println!("{:?}", nmea); } } else { break; } } } #[test] fn test_parse_all_logs() { for (i, log_path) in [ Path::new("tests") .join("data") .join("nmea_with_sat_info.log"), Path::new("tests").join("data").join("nmea1.log"), Path::new("tests").join("data").join("nmea2.log"), ] .iter() .enumerate() { println!("test parsing of {:?}", log_path); let full_log = fs::read_to_string(log_path).unwrap(); let mut nmea1 = Nmea::default(); let mut nmea2 = Nmea::default(); for (line_index, line) in full_log.lines().enumerate() { let line_no = line_index + 1; if line.starts_with("$GNGRS") || line.starts_with("$GNGST") || line.starts_with("$GNZDA") || line.starts_with("$GNGBS") { println!( "Ignoring unsupported {} at {:?}:{}", line, log_path, line_no ); continue; } let expect_msg = format!("Parsing of {} at {:?}:{} failed", line, log_path, line_no); parse_str(line).expect(&expect_msg); nmea1.parse(line).expect(&expect_msg); nmea2.parse_for_fix(line).expect(&expect_msg); } let sat_state = match i { 0 => vec![ "{Galileo 2 Some(56.0) Some(46.0) None}", "{Galileo 3 Some(11.0) Some(149.0) None}", "{Galileo 7 Some(54.0) Some(298.0) None}", "{Galileo 8 Some(60.0) Some(174.0) None}", "{Galileo 11 Some(1.0) Some(46.0) None}", "{Galileo 25 Some(8.0) Some(52.0) None}", "{Galileo 27 Some(11.0) Some(233.0) None}", "{Galileo 30 Some(66.0) Some(239.0) None}", "{Gps 5 Some(19.0) Some(222.0) Some(19.0)}", "{Gps 7 Some(5.0) Some(90.0) Some(18.0)}", "{Gps 13 Some(84.0) Some(239.0) Some(23.0)}", "{Gps 14 Some(56.0) Some(52.0) Some(16.0)}", "{Gps 15 Some(50.0) Some(296.0) Some(30.0)}", "{Gps 17 Some(35.0) Some(125.0) Some(24.0)}", "{Gps 19 Some(23.0) Some(147.0) None}", "{Gps 20 Some(3.0) Some(201.0) None}", "{Gps 23 Some(11.0) Some(319.0) Some(23.0)}", "{Gps 24 Some(16.0) Some(284.0) Some(25.0)}", "{Gps 28 Some(0.0) Some(0.0) Some(19.0)}", "{Gps 30 Some(28.0) Some(84.0) Some(20.0)}", "{Glonass 68 Some(39.0) Some(185.0) Some(28.0)}", "{Glonass 69 Some(63.0) Some(275.0) Some(34.0)}", "{Glonass 70 Some(14.0) Some(330.0) Some(22.0)}", "{Glonass 79 Some(61.0) Some(298.0) Some(36.0)}", "{Glonass 81 Some(0.0) Some(0.0) Some(17.0)}", "{Glonass 87 Some(14.0) Some(39.0) None}", "{Glonass 88 Some(15.0) Some(82.0) None}", "{Qzss 2 Some(11.0) Some(112.0) None}", "{Qzss 5 Some(28.0) Some(135.0) None}", "{Qzss 7 Some(22.0) Some(49.0) None}", "{Qzss 9 Some(2.0) Some(118.0) None}", "{Qzss 10 Some(36.0) Some(54.0) Some(18.0)}", "{Qzss 11 Some(20.0) Some(75.0) Some(18.0)}", "{Qzss 12 Some(5.0) Some(29.0) None}", "{Qzss 19 Some(0.0) Some(0.0) None}", "{Qzss 20 Some(37.0) Some(296.0) Some(30.0)}", "{Qzss 23 Some(66.0) Some(39.0) Some(17.0)}", "{Qzss 25 Some(19.0) Some(68.0) None}", "{Qzss 28 Some(3.0) Some(153.0) None}", ], 1 => vec![ "{Gps 1 Some(9.0) Some(74.0) None}", "{Gps 8 Some(3.0) Some(29.0) Some(22.0)}", "{Gps 10 Some(4.0) Some(350.0) Some(18.0)}", "{Gps 11 Some(19.0) Some(59.0) Some(19.0)}", "{Gps 13 Some(59.0) Some(220.0) None}", "{Gps 15 Some(45.0) Some(281.0) None}", "{Gps 17 Some(36.0) Some(151.0) None}", "{Gps 18 Some(11.0) Some(323.0) None}", "{Gps 19 Some(17.0) Some(170.0) None}", "{Gps 20 Some(6.0) Some(258.0) None}", "{Gps 24 Some(13.0) Some(288.0) None}", "{Gps 28 Some(65.0) Some(71.0) None}", "{Gps 30 Some(35.0) Some(109.0) None}", "{Glonass 65 Some(24.0) Some(229.0) None}", "{Glonass 66 Some(38.0) Some(296.0) None}", "{Glonass 67 Some(11.0) Some(347.0) Some(18.0)}", "{Glonass 74 Some(35.0) Some(78.0) None}", "{Glonass 75 Some(76.0) Some(343.0) None}", "{Glonass 76 Some(29.0) Some(279.0) None}", "{Glonass 83 Some(13.0) Some(12.0) Some(10.0)}", "{Glonass 84 Some(41.0) Some(67.0) None}", "{Glonass 85 Some(26.0) Some(132.0) None}", ], 2 => vec![ "{Gps 2 Some(35.0) Some(291.0) None}", "{Gps 3 Some(9.0) Some(129.0) None}", "{Gps 5 Some(14.0) Some(305.0) None}", "{Gps 6 Some(38.0) Some(226.0) None}", "{Gps 7 Some(56.0) Some(177.0) None}", "{Gps 9 Some(70.0) Some(67.0) None}", "{Gps 16 Some(20.0) Some(55.0) None}", "{Gps 23 Some(41.0) Some(76.0) None}", "{Gps 26 Some(10.0) Some(30.0) None}", "{Gps 29 Some(5.0) Some(341.0) None}", "{Gps 30 Some(26.0) Some(199.0) None}", "{Gps 36 Some(30.0) Some(158.0) None}", "{Gps 49 Some(32.0) Some(192.0) None}", "{Glonass 66 Some(45.0) Some(91.0) None}", "{Glonass 67 Some(67.0) Some(334.0) None}", "{Glonass 68 Some(17.0) Some(297.0) None}", "{Glonass 75 Some(13.0) Some(25.0) None}", "{Glonass 76 Some(49.0) Some(59.0) None}", "{Glonass 77 Some(40.0) Some(156.0) None}", "{Glonass 78 Some(0.0) Some(183.0) None}", "{Glonass 82 Some(15.0) Some(246.0) None}", "{Glonass 83 Some(28.0) Some(298.0) None}", "{Glonass 84 Some(10.0) Some(352.0) None}", ], _ => panic!("You need to add sat state for new log here"), }; assert_eq!(sat_state, format_satellites(nmea1.satellites())); assert_eq!(sat_state, format_satellites(nmea2.satellites())); } } fn err_to_string(e: E) -> String { e.to_string() } fn process_file(n: &Path) -> Result, String> { let input = BufReader::new(File::open(n).map_err(err_to_string)?); let mut nmea = nmea::Nmea::default(); let mut ret = Vec::with_capacity(15_000); for (num, line) in input.lines().enumerate() { let line = line .map_err(err_to_string) .map_err(|s| format!("{} at line {}", s, num + 1))?; let parse_res = nmea .parse(&line) .map_err(|s| format!("{:?} at line {}", s, num + 1))?; ret.push(format!("{:?}", parse_res)); } Ok(ret) }