{-# LANGUAGE QuasiQuotes #-} module Main where import qualified Track import Text.RawString.QQ(r) import Test.HUnit import qualified System.Exit as Exit import Control.Exception import Debug.Trace (trace, traceShow) import qualified Data.Time import Data.Either preamble = [r| <?xml version="1.0" encoding="UTF-8"?> <gpx version="1.1" creator="OpenTracks" xmlns="http://www.topografix.com/GPX/1/1" xmlns:topografix="http://www.topografix.com/GPX/Private/TopoGrafix/0/1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:opentracks="http://opentracksapp.com/xmlschemas/v1" xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v2" xmlns:gpxtrkx="http://www.garmin.com/xmlschemas/TrackStatsExtension/v1" xmlns:cluetrust="http://www.cluetrust.com/Schemas/" xmlns:pwr="http://www.garmin.com/xmlschemas/PowerExtension/v1" xsi:schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd http://www.topografix.com/GPX/Private/TopoGrafix/0/1 http://www.topografix.com/GPX/Private/TopoGrafix/0/1/topografix.xsd http://www.garmin.com/xmlschemas/TrackPointExtension/v2 https://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd http://www.garmin.com/xmlschemas/PowerExtension/v1 https://www8.garmin.com/xmlschemas/PowerExtensionv1.xsd http://www.garmin.com/xmlschemas/TrackStatsExtension/v1 http://www.cluetrust.com/Schemas http://www.cluetrust.com/Schemas/gpxdata10.xsd http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd"> |] wrap x = preamble ++ x ++ "</gpx>" onepoint = wrap [r| <trk> <trkseg> <trkpt lat="51" lon="-0.1"> </trkpt> </trkseg> </trk> |] onepointWithAttrs = wrap [r| <trk> <trkseg> <trkpt lat="51" lon="-0.1"> <ele>25.2</ele> <time>2024-10-23T08:34:59.779+01:00</time> <extensions><gpxtpx:TrackPointExtension> <gpxtpx:speed>2.4</gpxtpx:speed> <gpxtpx:cad>128</gpxtpx:cad> <pwr:PowerInWatts>55</pwr:PowerInWatts> <opentracks:accuracy_horizontal>3.216</opentracks:accuracy_horizontal><opentracks:distance>10.675</opentracks:distance> <cluetrust:distance>32.025</cluetrust:distance> </gpxtpx:TrackPointExtension> </extensions> </trkpt> </trkseg> </trk> |] test1 = TestCase $ either (assertFailure . displayException) (\ t -> assertEqual "empty track has no elements" 0 (Track.length t)) (Track.parse (wrap "")) testMalformed = TestCase $ let trk = Track.parse (wrap "<dgdsfg>>") in assertBool "catches syntax error" (isLeft trk) test2 = TestCase $ either (assertFailure . displayException) (\ trk -> case trk of p:_ -> assertEqual "matches lat/lon" (Track.Pos 51.0 (-0.1)) (Track.pos p) [] -> assertFailure "no points") (Track.parse onepoint) test3 = TestCase $ case Track.parse onepoint of Left err -> assertFailure (displayException err) Right (p:ps) -> assertEqual "matches attributes" (Nothing, Nothing) (Track.elevation p, Track.cadence p) Right [] -> assertFailure "no points" test4 = TestCase $ case Track.parse onepointWithAttrs of Left err -> assertFailure (displayException err) Right (p:ps) -> assertEqual "matches attributes" (Just 25.2, Just 128, Just 55, Data.Time.UTCTime (toEnum 60606) 27299.779) (Track.elevation p, Track.cadence p, Track.power p, Track.time p) Right [] -> assertFailure "no points" tests :: Test tests = TestList [ test1, testMalformed, test2, test3, test4 ] main :: IO () main = do result <- runTestTT tests if failures result > 0 then Exit.exitFailure else Exit.exitSuccess