UnitTest.hs (4766B)
1 {-# LANGUAGE QuasiQuotes #-} 2 3 module Main where 4 5 import Control.Exception 6 import Data.Either 7 import Data.List as List 8 import Data.Time qualified 9 import Debug.Trace (trace, traceShow) 10 import System.Exit qualified as Exit 11 import Test.HUnit 12 import Text.RawString.QQ (r) 13 import Track qualified 14 15 preamble = 16 [r| 17 <?xml version="1.0" encoding="UTF-8"?> 18 <gpx 19 version="1.1" 20 creator="OpenTracks" 21 xmlns="http://www.topografix.com/GPX/1/1" 22 xmlns:topografix="http://www.topografix.com/GPX/Private/TopoGrafix/0/1" 23 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 24 xmlns:opentracks="http://opentracksapp.com/xmlschemas/v1" 25 xmlns:gpxtpx="http://www.garmin.com/xmlschemas/TrackPointExtension/v2" 26 xmlns:gpxtrkx="http://www.garmin.com/xmlschemas/TrackStatsExtension/v1" 27 xmlns:cluetrust="http://www.cluetrust.com/Schemas/" 28 xmlns:pwr="http://www.garmin.com/xmlschemas/PowerExtension/v1" 29 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"> 30 |] 31 32 wrap x = preamble ++ x ++ "</gpx>" 33 34 wrapPoint x = 35 let trk = "<trk><trkseg>" ++ x ++ "</trkseg></trk>" 36 in wrap trk 37 38 onepoint = 39 wrap 40 [r| 41 <trk> <trkseg> 42 <trkpt lat="51" lon="-0.1"> 43 <time>2024-10-23T08:34:59.779+01:00</time> 44 </trkpt> 45 </trkseg> </trk> 46 |] 47 48 onepointWithAttrs = 49 wrap 50 [r| 51 <trk> 52 <trkseg> 53 <trkpt lat="51" lon="-0.1"> 54 <ele>25.2</ele> 55 <time>2024-10-23T08:34:59.779+01:00</time> 56 <extensions><gpxtpx:TrackPointExtension> 57 <gpxtpx:speed>2.4</gpxtpx:speed> 58 <gpxtpx:cad>128</gpxtpx:cad> 59 <gpxtpx:hr>160</gpxtpx:hr> 60 <pwr:PowerInWatts>55</pwr:PowerInWatts> 61 <opentracks:accuracy_horizontal>3.216</opentracks:accuracy_horizontal><opentracks:distance>10.675</opentracks:distance> 62 <cluetrust:distance>32.025</cluetrust:distance> 63 </gpxtpx:TrackPointExtension> 64 </extensions> 65 </trkpt> 66 </trkseg> 67 </trk> 68 |] 69 70 test1 = 71 TestCase $ 72 either 73 (assertFailure . displayException) 74 ( assertEqual 75 "empty track has no elements" 76 0 77 . Track.length 78 ) 79 (Track.parse (wrap "")) 80 81 testMalformed = 82 TestCase $ 83 let trk = Track.parse (wrap "<dgdsfg>>") 84 in assertBool "catches syntax error" (isLeft trk) 85 86 testMissingAttrs = 87 let els = 88 [ [r| 89 <trkpt lon="2" latsdf="51"> 90 <time>2024-10-23T08:34:59.779+01:00</time> 91 </trkpt> 92 |], 93 [r| 94 <trkpt lon="dsfgsdfg" lat="51"> 95 <time>2024-10-23T08:34:59.779+01:00</time> 96 </trkpt> 97 |], 98 [r| 99 <trkpt lon="2" lat="51"> 100 <time>2024-10-23G87sdCfdfgsdfhg</time> 101 </trkpt> 102 |] 103 ] 104 in TestCase $ 105 assertBool 106 "failed to catch missing/malformed attribute" 107 (List.all (isLeft . Track.parse . wrapPoint) els) 108 109 test2 = 110 TestList 111 [ TestCase $ 112 either 113 (assertFailure . displayException) 114 ( \(p : _) -> 115 assertEqual 116 "matches lat/lon" 117 (Track.Pos 51.0 (-0.1) Nothing) 118 (Track.pos p) 119 ) 120 (Track.parse onepoint), 121 TestCase $ 122 either 123 (assertFailure . displayException) 124 ( \(p : _) -> 125 assertEqual 126 "matches lat/lon" 127 (Track.Pos 51.0 (-0.1) (Just 25.2)) 128 (Track.pos p) 129 ) 130 (Track.parse onepointWithAttrs) 131 ] 132 133 test3 = 134 TestCase $ 135 either 136 (assertFailure . displayException) 137 ( \(p : _) -> 138 assertEqual 139 "handles missing attributes" 140 (Nothing, Nothing) 141 (Track.power p, Track.cadence p) 142 ) 143 (Track.parse onepoint) 144 145 test4 = 146 TestCase $ 147 either 148 (assertFailure . displayException) 149 ( \(p : _) -> 150 assertEqual 151 "handles attributes" 152 (Just 128, Just 55, Data.Time.UTCTime (toEnum 60606) 27299.779, Just 160) 153 (Track.cadence p, Track.power p, Track.time p, Track.heartRate p) 154 ) 155 (Track.parse onepointWithAttrs) 156 157 tests :: Test 158 tests = 159 TestList 160 [ test1, 161 testMalformed, 162 testMissingAttrs, 163 test2, 164 test3, 165 test4 166 ] 167 168 main :: IO () 169 main = do 170 result <- runTestTT tests 171 if (failures result > 0) || (errors result > 0) 172 then Exit.exitFailure 173 else Exit.exitSuccess