]> Git — Sourcephile - comptalang.git/blob - lib/Test/Main.hs
Correction : Data.List.foldl -> Data.List.foldl'
[comptalang.git] / lib / Test / Main.hs
1 {-# LANGUAGE TupleSections #-}
2 {-# LANGUAGE OverloadedStrings #-}
3
4 import Prelude
5 import Test.HUnit
6 import Test.Framework.Providers.HUnit (hUnitTestToTests)
7 import Test.Framework.Runners.Console (defaultMain)
8
9 import Control.Applicative ((<*))
10 import Control.Arrow ((***))
11 import Control.Monad.IO.Class (liftIO)
12 import Data.Decimal (DecimalRaw(..))
13 import qualified Data.Either
14 import qualified Data.List
15 import Data.List.NonEmpty (NonEmpty(..))
16 import qualified Data.Map.Strict as Data.Map
17 import Data.Text (Text)
18 import qualified Data.Time.Calendar as Time
19 import qualified Data.Time.LocalTime as Time
20 import qualified Text.Parsec as P
21 import qualified Text.Parsec.Pos as P
22 -- import qualified Text.PrettyPrint.Leijen.Text as PP
23
24 import qualified Hcompta.Model.Account as Account
25 import qualified Hcompta.Model.Amount as Amount
26 import qualified Hcompta.Model.Amount.Style as Amount.Style
27 import qualified Hcompta.Model.Date as Date
28 import qualified Hcompta.Model.Transaction as Transaction
29 import qualified Hcompta.Model.Transaction.Posting as Posting
30 import qualified Hcompta.Calc.Balance as Calc.Balance
31 import qualified Hcompta.Format.Ledger.Read as Format.Ledger.Read
32 import qualified Hcompta.Format.Ledger.Journal as Format.Ledger.Journal
33 import qualified Hcompta.Format.Ledger.Write as Format.Ledger.Write
34 import qualified Hcompta.Lib.TreeMap as Lib.TreeMap
35 import qualified Hcompta.Lib.Parsec as P
36 import qualified Hcompta.Lib.Foldable as Lib.Foldable
37
38 --instance Eq Text.Parsec.ParseError where
39 -- (==) = const (const False)
40
41 main :: IO ()
42 main = defaultMain $ hUnitTestToTests test_Hcompta
43
44 test_Hcompta :: Test
45 test_Hcompta =
46 TestList
47 [ "Lib" ~: TestList
48 [ "TreeMap" ~: TestList
49 [ "insert" ~: TestList
50 [ "[] 0" ~:
51 (Lib.TreeMap.insert const ((0::Int):|[]) () Lib.TreeMap.empty)
52 ~?=
53 (Lib.TreeMap.TreeMap $
54 Data.Map.fromList
55 [ ((0::Int), Lib.TreeMap.leaf ())
56 ])
57 , "[] 0/1" ~:
58 (Lib.TreeMap.insert const ((0::Int):|1:[]) () Lib.TreeMap.empty)
59 ~?=
60 (Lib.TreeMap.TreeMap $
61 Data.Map.fromList
62 [ ((0::Int), Lib.TreeMap.Node
63 { Lib.TreeMap.node_value = Nothing
64 , Lib.TreeMap.node_size = 1
65 , Lib.TreeMap.node_descendants =
66 Lib.TreeMap.singleton ((1::Int):|[]) ()
67 })
68 ])
69 ]
70 , "union" ~: TestList
71 [
72 ]
73 , "map_by_depth_first" ~: TestList
74 [
75 ]
76 , "flatten" ~: TestList
77 [ "[0, 0/1, 0/1/2]" ~:
78 (Lib.TreeMap.flatten id $
79 Lib.TreeMap.from_List const
80 [ ((0:|[]), ())
81 , ((0:|1:[]), ())
82 , ((0:|1:2:[]), ())
83 ]
84 )
85 ~?=
86 (Data.Map.fromList
87 [ ((0:|[]), ())
88 , ((0:|1:[]), ())
89 , ((0:|1:2:[]), ())
90 ])
91 , "[1, 1/2, 1/22, 1/2/3, 1/2/33, 11, 11/2, 11/2/3, 11/2/33]" ~:
92 (Lib.TreeMap.flatten id $
93 Lib.TreeMap.from_List const
94 [ ((1:|[]), ())
95 , ((1:|2:[]), ())
96 , ((1:|22:[]), ())
97 , ((1:|2:3:[]), ())
98 , ((1:|2:33:[]), ())
99 , ((11:|[]), ())
100 , ((11:|2:[]), ())
101 , ((11:|2:3:[]), ())
102 , ((11:|2:33:[]), ())
103 ]
104 )
105 ~?=
106 (Data.Map.fromList
107 [ ((1:|[]), ())
108 , ((1:|2:[]), ())
109 , ((1:|22:[]), ())
110 , ((1:|2:3:[]), ())
111 , ((1:|2:33:[]), ())
112 , ((11:|[]), ())
113 , ((11:|2:[]), ())
114 , ((11:|2:3:[]), ())
115 , ((11:|2:33:[]), ())
116 ])
117 ]
118 ]
119 , "Foldable" ~: TestList
120 [ "accumLeftsAndFoldrRights" ~: TestList
121 [ "Left" ~:
122 (Lib.Foldable.accumLeftsAndFoldrRights (++) [""] $
123 [Left [0]])
124 ~?=
125 (([0], [""]))
126 , "repeat Left" ~:
127 ((take 1 *** take 0) $
128 Lib.Foldable.accumLeftsAndFoldrRights (++) [""] $
129 ( repeat (Left [0]) ))
130 ~?=
131 ([0], [])
132 , "Right:Left:Right:Left" ~:
133 (Lib.Foldable.accumLeftsAndFoldrRights (++) ["0"] $
134 ( Right ["2"]:Left [1]:Right ["1"]:Left [0]:[] ))
135 ~?=
136 ([1, 0], ["2", "1", "0"])
137 , "Right:Left:Right:repeat Left" ~:
138 ((take 1 *** take 2) $
139 Lib.Foldable.accumLeftsAndFoldrRights (++) ["0"] $
140 ( Right ["2"]:Left [1]:Right ["1"]:repeat (Left [0]) ))
141 ~?=
142 ([1], ["2", "1"])
143 ]
144 ]
145 ]
146 , "Model" ~: TestList
147 [ "Account" ~: TestList
148 [ "foldr" ~: TestList
149 [ "[A]" ~:
150 (reverse $ Account.foldr ("A":|[]) (:) []) ~?= ["A":|[]]
151 , "[A, B]" ~:
152 (reverse $ Account.foldr ("A":|["B"]) (:) []) ~?= ["A":|[], "A":|["B"]]
153 , "[A, B, C]" ~:
154 (reverse $ Account.foldr ("A":|["B", "C"]) (:) []) ~?= ["A":|[], "A":|["B"], "A":|["B", "C"]]
155 ]
156 , "ascending" ~: TestList
157 [ "[A]" ~:
158 Account.ascending ("A":|[]) ~?= Nothing
159 , "[A, B]" ~:
160 Account.ascending ("A":|["B"]) ~?= Just ("A":|[])
161 , "[A, B, C]" ~:
162 Account.ascending ("A":|["B", "C"]) ~?= Just ("A":|["B"])
163 ]
164 ]
165 , "Amount" ~: TestList
166 [ "+" ~: TestList
167 [ "$1 + 1$ = $2" ~:
168 (+)
169 (Amount.nil
170 { Amount.quantity = Decimal 0 1
171 , Amount.style = Amount.Style.nil
172 { Amount.Style.unit_side = Just $ Amount.Style.Side_Left
173 }
174 , Amount.unit = "$"
175 })
176 (Amount.nil
177 { Amount.quantity = Decimal 0 1
178 , Amount.style = Amount.Style.nil
179 { Amount.Style.unit_side = Just $ Amount.Style.Side_Right
180 }
181 , Amount.unit = "$"
182 })
183 ~?=
184 (Amount.nil
185 { Amount.quantity = Decimal 0 2
186 , Amount.style = Amount.Style.nil
187 { Amount.Style.unit_side = Just $ Amount.Style.Side_Left
188 }
189 , Amount.unit = "$"
190 })
191 ]
192 , "from_List" ~: TestList
193 [ "from_List [$1, 1$] = $2" ~:
194 Amount.from_List
195 [ Amount.nil
196 { Amount.quantity = Decimal 0 1
197 , Amount.style = Amount.Style.nil
198 { Amount.Style.unit_side = Just $ Amount.Style.Side_Left
199 }
200 , Amount.unit = "$"
201 }
202 , Amount.nil
203 { Amount.quantity = Decimal 0 1
204 , Amount.style = Amount.Style.nil
205 { Amount.Style.unit_side = Just $ Amount.Style.Side_Right
206 }
207 , Amount.unit = "$"
208 }
209 ]
210 ~?=
211 Data.Map.fromList
212 [ ("$", Amount.nil
213 { Amount.quantity = Decimal 0 2
214 , Amount.style = Amount.Style.nil
215 { Amount.Style.unit_side = Just $ Amount.Style.Side_Left
216 }
217 , Amount.unit = "$"
218 })
219 ]
220 ]
221 ]
222 ]
223 , "Calc" ~: TestList
224 [ "Balance" ~: TestList
225 [ "posting" ~: TestList
226 [ "[A+$1] = A+$1 & $+1" ~:
227 (Calc.Balance.posting
228 (Posting.nil ("A":|[]))
229 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ]
230 }
231 Calc.Balance.nil)
232 ~?=
233 Calc.Balance.Balance
234 { Calc.Balance.by_account =
235 Lib.TreeMap.from_List const
236 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
237 , Calc.Balance.by_unit =
238 Data.Map.fromList $
239 Data.List.map Calc.Balance.assoc_unit_sum $
240 [ Calc.Balance.Unit_Sum
241 { Calc.Balance.amount = Amount.usd $ 1
242 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
243 ["A":|[]]
244 }
245 ]
246 }
247 , "[A+$1, A-$1] = {A+$0, $+0}" ~:
248 (Data.List.foldl
249 (flip Calc.Balance.posting)
250 Calc.Balance.nil
251 [ (Posting.nil ("A":|[]))
252 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ]
253 }
254 , (Posting.nil ("A":|[]))
255 { Posting.amounts=Amount.from_List [ Amount.usd $ -1 ]
256 }
257 ])
258 ~?=
259 Calc.Balance.Balance
260 { Calc.Balance.by_account =
261 Lib.TreeMap.from_List const
262 [ ("A":|[], Amount.from_List [ Amount.usd $ 0 ]) ]
263 , Calc.Balance.by_unit =
264 Data.Map.fromList $
265 Data.List.map Calc.Balance.assoc_unit_sum $
266 [ Calc.Balance.Unit_Sum
267 { Calc.Balance.amount = Amount.usd $ 0
268 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
269 ["A":|[]]
270 }
271 ]
272 }
273 , "[A+$1, A-€1] = {A+$1-€1, $+1 €-1}" ~:
274 (Data.List.foldl
275 (flip Calc.Balance.posting)
276 Calc.Balance.nil
277 [ (Posting.nil ("A":|[]))
278 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ]
279 }
280 , (Posting.nil ("A":|[]))
281 { Posting.amounts=Amount.from_List [ Amount.eur $ -1 ]
282 }
283 ])
284 ~?=
285 Calc.Balance.Balance
286 { Calc.Balance.by_account =
287 Lib.TreeMap.from_List const
288 [ ("A":|[], Amount.from_List [ Amount.usd $ 1, Amount.eur $ -1 ]) ]
289 , Calc.Balance.by_unit =
290 Data.Map.fromList $
291 Data.List.map Calc.Balance.assoc_unit_sum $
292 [ Calc.Balance.Unit_Sum
293 { Calc.Balance.amount = Amount.usd $ 1
294 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
295 ["A":|[]]
296 }
297 , Calc.Balance.Unit_Sum
298 { Calc.Balance.amount = Amount.eur $ -1
299 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
300 ["A":|[]]
301 }
302 ]
303 }
304 , "[A+$1, B-$1] = {A+$1 B-$1, $+0}" ~:
305 (Data.List.foldl
306 (flip Calc.Balance.posting)
307 Calc.Balance.nil
308 [ (Posting.nil ("A":|[]))
309 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ]
310 }
311 , (Posting.nil ("B":|[]))
312 { Posting.amounts=Amount.from_List [ Amount.usd $ -1 ]
313 }
314 ])
315 ~?=
316 Calc.Balance.Balance
317 { Calc.Balance.by_account =
318 Lib.TreeMap.from_List const
319 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
320 , ("B":|[], Amount.from_List [ Amount.usd $ -1 ])
321 ]
322 , Calc.Balance.by_unit =
323 Data.Map.fromList $
324 Data.List.map Calc.Balance.assoc_unit_sum $
325 [ Calc.Balance.Unit_Sum
326 { Calc.Balance.amount = Amount.usd $ 0
327 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
328 ["A":|[], "B":|[]]
329 }
330 ]
331 }
332 , "[A+$1, B+$1]" ~:
333 (Data.List.foldl
334 (flip Calc.Balance.posting)
335 Calc.Balance.nil
336 [ (Posting.nil ("A":|[]))
337 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ]
338 }
339 , (Posting.nil ("B":|[]))
340 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ]
341 }
342 ])
343 ~?=
344 Calc.Balance.Balance
345 { Calc.Balance.by_account =
346 Lib.TreeMap.from_List const
347 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
348 , ("B":|[], Amount.from_List [ Amount.usd $ 1 ])
349 ]
350 , Calc.Balance.by_unit =
351 Data.Map.fromList $
352 Data.List.map Calc.Balance.assoc_unit_sum $
353 [ Calc.Balance.Unit_Sum
354 { Calc.Balance.amount = Amount.usd $ 2
355 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
356 ["A":|[], "B":|[]]
357 }
358 ]
359 }
360 , "[A+$1+€2, A-$1-€2] = {A+$0+€0, $+0 €+0}" ~:
361 (Data.List.foldl
362 (flip Calc.Balance.posting)
363 Calc.Balance.nil
364 [ (Posting.nil ("A":|[]))
365 { Posting.amounts=Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2 ]
366 }
367 , (Posting.nil ("A":|[]))
368 { Posting.amounts=Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2 ]
369 }
370 ])
371 ~?=
372 Calc.Balance.Balance
373 { Calc.Balance.by_account =
374 Lib.TreeMap.from_List const
375 [ ("A":|[], Amount.from_List [ Amount.usd $ 0, Amount.eur $ 0 ])
376 ]
377 , Calc.Balance.by_unit =
378 Data.Map.fromList $
379 Data.List.map Calc.Balance.assoc_unit_sum $
380 [ Calc.Balance.Unit_Sum
381 { Calc.Balance.amount = Amount.usd $ 0
382 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
383 ["A":|[]]
384 }
385 , Calc.Balance.Unit_Sum
386 { Calc.Balance.amount = Amount.eur $ 0
387 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
388 ["A":|[]]
389 }
390 ]
391 }
392 , "[A+$1+€2+£3, B-$1-2€-£3] = {A+$1+€2+£3 B-$1-€2-£3, $+0 €+0 £+0}" ~:
393 (Data.List.foldl
394 (flip Calc.Balance.posting)
395 Calc.Balance.nil
396 [ (Posting.nil ("A":|[]))
397 { Posting.amounts=Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ]
398 }
399 , (Posting.nil ("B":|[]))
400 { Posting.amounts=Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ]
401 }
402 ])
403 ~?=
404 Calc.Balance.Balance
405 { Calc.Balance.by_account =
406 Lib.TreeMap.from_List const
407 [ ("A":|[], Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ])
408 , ("B":|[], Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ])
409 ]
410 , Calc.Balance.by_unit =
411 Data.Map.fromList $
412 Data.List.map Calc.Balance.assoc_unit_sum $
413 [ Calc.Balance.Unit_Sum
414 { Calc.Balance.amount = Amount.usd $ 0
415 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
416 ["A":|[], "B":|[]]
417 }
418 , Calc.Balance.Unit_Sum
419 { Calc.Balance.amount = Amount.eur $ 0
420 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
421 ["A":|[], "B":|[]]
422 }
423 , Calc.Balance.Unit_Sum
424 { Calc.Balance.amount = Amount.gbp $ 0
425 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
426 ["A":|[], "B":|[]]
427 }
428 ]
429 }
430 ]
431 , "union" ~: TestList
432 [ "nil nil = nil" ~:
433 Calc.Balance.union
434 Calc.Balance.nil
435 Calc.Balance.nil
436 ~?=
437 Calc.Balance.nil
438 , "{A+$1, $+1} {A+$1, $+1} = {A+$2, $+2}" ~:
439 Calc.Balance.union
440 (Calc.Balance.Balance
441 { Calc.Balance.by_account =
442 Lib.TreeMap.from_List const
443 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
444 , Calc.Balance.by_unit =
445 Data.Map.fromList $
446 Data.List.map Calc.Balance.assoc_unit_sum $
447 [ Calc.Balance.Unit_Sum
448 { Calc.Balance.amount = Amount.usd $ 1
449 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
450 ["A":|[]]
451 }
452 ]
453 })
454 (Calc.Balance.Balance
455 { Calc.Balance.by_account =
456 Lib.TreeMap.from_List const
457 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
458 , Calc.Balance.by_unit =
459 Data.Map.fromList $
460 Data.List.map Calc.Balance.assoc_unit_sum $
461 [ Calc.Balance.Unit_Sum
462 { Calc.Balance.amount = Amount.usd $ 1
463 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
464 ["A":|[]]
465 }
466 ]
467 })
468 ~?=
469 Calc.Balance.Balance
470 { Calc.Balance.by_account =
471 Lib.TreeMap.from_List const
472 [ ("A":|[], Amount.from_List [ Amount.usd $ 2 ]) ]
473 , Calc.Balance.by_unit =
474 Data.Map.fromList $
475 Data.List.map Calc.Balance.assoc_unit_sum $
476 [ Calc.Balance.Unit_Sum
477 { Calc.Balance.amount = Amount.usd $ 2
478 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
479 ["A":|[]]
480 }
481 ]
482 }
483 , "{A+$1, $+1} {B+$1, $+1} = {A+$1 B+$1, $+2}" ~:
484 Calc.Balance.union
485 (Calc.Balance.Balance
486 { Calc.Balance.by_account =
487 Lib.TreeMap.from_List const
488 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
489 , Calc.Balance.by_unit =
490 Data.Map.fromList $
491 Data.List.map Calc.Balance.assoc_unit_sum $
492 [ Calc.Balance.Unit_Sum
493 { Calc.Balance.amount = Amount.usd $ 1
494 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
495 ["A":|[]]
496 }
497 ]
498 })
499 (Calc.Balance.Balance
500 { Calc.Balance.by_account =
501 Lib.TreeMap.from_List const
502 [ ("B":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
503 , Calc.Balance.by_unit =
504 Data.Map.fromList $
505 Data.List.map Calc.Balance.assoc_unit_sum $
506 [ Calc.Balance.Unit_Sum
507 { Calc.Balance.amount = Amount.usd $ 1
508 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
509 ["B":|[]]
510 }
511 ]
512 })
513 ~?=
514 Calc.Balance.Balance
515 { Calc.Balance.by_account =
516 Lib.TreeMap.from_List const
517 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
518 , ("B":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
519 , Calc.Balance.by_unit =
520 Data.Map.fromList $
521 Data.List.map Calc.Balance.assoc_unit_sum $
522 [ Calc.Balance.Unit_Sum
523 { Calc.Balance.amount = Amount.usd $ 2
524 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
525 ["A":|[], "B":|[]]
526 }
527 ]
528 }
529 , "{A+$1, $+1} {B+€1, €+1} = {A+$1 B+€1, $+1 €+1}" ~:
530 Calc.Balance.union
531 (Calc.Balance.Balance
532 { Calc.Balance.by_account =
533 Lib.TreeMap.from_List const
534 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ]
535 , Calc.Balance.by_unit =
536 Data.Map.fromList $
537 Data.List.map Calc.Balance.assoc_unit_sum $
538 [ Calc.Balance.Unit_Sum
539 { Calc.Balance.amount = Amount.usd $ 1
540 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
541 ["A":|[]]
542 }
543 ]
544 })
545 (Calc.Balance.Balance
546 { Calc.Balance.by_account =
547 Lib.TreeMap.from_List const
548 [ ("B":|[], Amount.from_List [ Amount.eur $ 1 ]) ]
549 , Calc.Balance.by_unit =
550 Data.Map.fromList $
551 Data.List.map Calc.Balance.assoc_unit_sum $
552 [ Calc.Balance.Unit_Sum
553 { Calc.Balance.amount = Amount.eur $ 1
554 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
555 ["B":|[]]
556 }
557 ]
558 })
559 ~?=
560 Calc.Balance.Balance
561 { Calc.Balance.by_account =
562 Lib.TreeMap.from_List const
563 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
564 , ("B":|[], Amount.from_List [ Amount.eur $ 1 ]) ]
565 , Calc.Balance.by_unit =
566 Data.Map.fromList $
567 Data.List.map Calc.Balance.assoc_unit_sum $
568 [ Calc.Balance.Unit_Sum
569 { Calc.Balance.amount = Amount.usd $ 1
570 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
571 ["A":|[]]
572 }
573 , Calc.Balance.Unit_Sum
574 { Calc.Balance.amount = Amount.eur $ 1
575 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
576 ["B":|[]]
577 }
578 ]
579 }
580 ]
581 , "expanded" ~: TestList
582 [ "nil_By_Account" ~:
583 Calc.Balance.expanded
584 Calc.Balance.nil_By_Account
585 ~?=
586 Lib.TreeMap.empty
587 , "A+$1 = A+$1" ~:
588 Calc.Balance.expanded
589 (Lib.TreeMap.from_List const
590 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ]) ])
591 ~?=
592 (Lib.TreeMap.from_List const
593 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
594 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
595 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
596 })
597 ])
598 , "A/A+$1 = A+$1 A/A+$1" ~:
599 Calc.Balance.expanded
600 (Lib.TreeMap.from_List const
601 [ ("A":|["A"], Amount.from_List [ Amount.usd $ 1 ]) ])
602 ~?=
603 (Lib.TreeMap.from_List const
604 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
605 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
606 , Calc.Balance.exclusive = Amount.from_List []
607 })
608 , ("A":|["A"], Calc.Balance.Account_Sum_Expanded
609 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
610 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
611 })
612 ])
613 , "A/B+$1 = A+$1 A/B+$1" ~:
614 Calc.Balance.expanded
615 (Lib.TreeMap.from_List const
616 [ ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ]) ])
617 ~?=
618 (Lib.TreeMap.from_List const
619 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
620 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
621 , Calc.Balance.exclusive = Amount.from_List []
622 })
623 , ("A":|["B"], Calc.Balance.Account_Sum_Expanded
624 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
625 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
626 })
627 ])
628 , "A/B/C+$1 = A+$1 A/B+$1 A/B/C+$1" ~:
629 Calc.Balance.expanded
630 (Lib.TreeMap.from_List const
631 [ ("A":|["B", "C"], Amount.from_List [ Amount.usd $ 1 ]) ])
632 ~?=
633 (Lib.TreeMap.from_List const
634 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
635 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
636 , Calc.Balance.exclusive = Amount.from_List []
637 })
638 , ("A":|["B"], Calc.Balance.Account_Sum_Expanded
639 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
640 , Calc.Balance.exclusive = Amount.from_List []
641 })
642 , ("A":|["B", "C"], Calc.Balance.Account_Sum_Expanded
643 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
644 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
645 })
646 ])
647 , "A+$1 A/B+$1 = A+$2 A/B+$1" ~:
648 Calc.Balance.expanded
649 (Lib.TreeMap.from_List const
650 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
651 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
652 ])
653 ~?=
654 (Lib.TreeMap.from_List const
655 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
656 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 2 ]
657 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
658 })
659 , ("A":|["B"], Calc.Balance.Account_Sum_Expanded
660 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
661 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
662 })
663 ])
664 , "A+$1 A/B+$1 A/B/C+$1 = A+$3 A/B+$2 A/B/C+$1" ~:
665 Calc.Balance.expanded
666 (Lib.TreeMap.from_List const
667 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
668 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
669 , ("A":|["B", "C"], Amount.from_List [ Amount.usd $ 1 ])
670 ])
671 ~?=
672 (Lib.TreeMap.from_List const
673 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
674 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 3 ]
675 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
676 })
677 , ("A":|["B"], Calc.Balance.Account_Sum_Expanded
678 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 2 ]
679 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
680 })
681 , ("A":|["B", "C"], Calc.Balance.Account_Sum_Expanded
682 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
683 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
684 })
685 ])
686 , "A+$1 A/B+$1 A/B/C+$1 A/B/C/D+$1 = A+$4 A/B+$3 A/B/C+$2 A/B/C/D+$1" ~:
687 Calc.Balance.expanded
688 (Lib.TreeMap.from_List const
689 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
690 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
691 , ("A":|["B", "C"], Amount.from_List [ Amount.usd $ 1 ])
692 , ("A":|["B", "C", "D"], Amount.from_List [ Amount.usd $ 1 ])
693 ])
694 ~?=
695 (Lib.TreeMap.from_List const
696 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
697 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 4 ]
698 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
699 })
700 , ("A":|["B"], Calc.Balance.Account_Sum_Expanded
701 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 3 ]
702 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
703 })
704 , ("A":|["B", "C"], Calc.Balance.Account_Sum_Expanded
705 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 2 ]
706 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
707 })
708 , ("A":|["B", "C", "D"], Calc.Balance.Account_Sum_Expanded
709 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
710 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
711 })
712 ])
713 , "A+$1 A/B+$1 A/BB+$1 AA/B+$1 = A+$3 A/B+$1 A/BB+$1 AA+$1 AA/B+$1" ~:
714 Calc.Balance.expanded
715 (Lib.TreeMap.from_List const
716 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
717 , ("A":|["B"], Amount.from_List [ Amount.usd $ 1 ])
718 , ("A":|["BB"], Amount.from_List [ Amount.usd $ 1 ])
719 , ("AA":|["B"], Amount.from_List [ Amount.usd $ 1 ])
720 ])
721 ~?=
722 (Lib.TreeMap.from_List const
723 [ ("A":|[], Calc.Balance.Account_Sum_Expanded
724 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 3 ]
725 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
726 })
727 , ("A":|["B"], Calc.Balance.Account_Sum_Expanded
728 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
729 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
730 })
731 , ("A":|["BB"], Calc.Balance.Account_Sum_Expanded
732 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
733 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
734 })
735 , ("AA":|[], Calc.Balance.Account_Sum_Expanded
736 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
737 , Calc.Balance.exclusive = Amount.from_List []
738 })
739 , ("AA":|["B"], Calc.Balance.Account_Sum_Expanded
740 { Calc.Balance.inclusive = Amount.from_List [ Amount.usd $ 1 ]
741 , Calc.Balance.exclusive = Amount.from_List [ Amount.usd $ 1 ]
742 })
743 ])
744 ]
745 , "deviation" ~: TestList
746 [ "{A+$1, $1}" ~:
747 (Calc.Balance.deviation $
748 Calc.Balance.Balance
749 { Calc.Balance.by_account =
750 Lib.TreeMap.from_List const
751 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
752 , ("B":|[], Amount.from_List [])
753 ]
754 , Calc.Balance.by_unit =
755 Data.Map.fromList $
756 Data.List.map Calc.Balance.assoc_unit_sum $
757 [ Calc.Balance.Unit_Sum
758 { Calc.Balance.amount = Amount.usd $ 1
759 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
760 ["A":|[]]
761 }
762 ]
763 })
764 ~?=
765 (Calc.Balance.Deviation $
766 Data.Map.fromList $
767 Data.List.map Calc.Balance.assoc_unit_sum $
768 [ Calc.Balance.Unit_Sum
769 { Calc.Balance.amount = Amount.usd $ 1
770 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
771 ["B":|[]]
772 }
773 ])
774 , "{A+$1 B+$1, $2}" ~:
775 (Calc.Balance.deviation $
776 Calc.Balance.Balance
777 { Calc.Balance.by_account =
778 Lib.TreeMap.from_List const
779 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
780 , ("B":|[], Amount.from_List [ Amount.usd $ 1 ])
781 ]
782 , Calc.Balance.by_unit =
783 Data.Map.fromList $
784 Data.List.map Calc.Balance.assoc_unit_sum $
785 [ Calc.Balance.Unit_Sum
786 { Calc.Balance.amount = Amount.usd $ 2
787 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
788 [ "A":|[]
789 , "B":|[]
790 ]
791 }
792 ]
793 })
794 ~?=
795 (Calc.Balance.Deviation $
796 Data.Map.fromList $
797 Data.List.map Calc.Balance.assoc_unit_sum $
798 [ Calc.Balance.Unit_Sum
799 { Calc.Balance.amount = Amount.usd $ 2
800 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
801 [
802 ]
803 }
804 ])
805 ]
806 , "is_equilibrium_inferrable" ~: TestList
807 [ "nil" ~: TestCase $
808 (@=?) True $
809 Calc.Balance.is_equilibrium_inferrable $
810 Calc.Balance.deviation $
811 Calc.Balance.nil
812 , "{A+$0, $+0}" ~: TestCase $
813 (@=?) True $
814 Calc.Balance.is_equilibrium_inferrable $
815 Calc.Balance.deviation $
816 Calc.Balance.Balance
817 { Calc.Balance.by_account =
818 Lib.TreeMap.from_List const
819 [ ("A":|[], Amount.from_List [ Amount.usd $ 0 ])
820 ]
821 , Calc.Balance.by_unit =
822 Data.Map.fromList $
823 Data.List.map Calc.Balance.assoc_unit_sum $
824 [ Calc.Balance.Unit_Sum
825 { Calc.Balance.amount = Amount.usd $ 0
826 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
827 ["A":|[]]
828 }
829 ]
830 }
831 , "{A+$1, $+1}" ~: TestCase $
832 (@=?) False $
833 Calc.Balance.is_equilibrium_inferrable $
834 Calc.Balance.deviation $
835 Calc.Balance.Balance
836 { Calc.Balance.by_account =
837 Lib.TreeMap.from_List const
838 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
839 ]
840 , Calc.Balance.by_unit =
841 Data.Map.fromList $
842 Data.List.map Calc.Balance.assoc_unit_sum $
843 [ Calc.Balance.Unit_Sum
844 { Calc.Balance.amount = Amount.usd $ 1
845 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
846 ["A":|[]]
847 }
848 ]
849 }
850 , "{A+$0+€0, $0 €+0}" ~: TestCase $
851 (@=?) True $
852 Calc.Balance.is_equilibrium_inferrable $
853 Calc.Balance.deviation $
854 Calc.Balance.Balance
855 { Calc.Balance.by_account =
856 Lib.TreeMap.from_List const
857 [ ("A":|[], Amount.from_List [ Amount.usd $ 0, Amount.eur $ 0 ])
858 ]
859 , Calc.Balance.by_unit =
860 Data.Map.fromList $
861 Data.List.map Calc.Balance.assoc_unit_sum $
862 [ Calc.Balance.Unit_Sum
863 { Calc.Balance.amount = Amount.usd $ 0
864 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
865 ["A":|[]]
866 }
867 , Calc.Balance.Unit_Sum
868 { Calc.Balance.amount = Amount.eur $ 0
869 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
870 ["A":|[]]
871 }
872 ]
873 }
874 , "{A+$1, B-$1, $+0}" ~: TestCase $
875 (@=?) True $
876 Calc.Balance.is_equilibrium_inferrable $
877 Calc.Balance.deviation $
878 Calc.Balance.Balance
879 { Calc.Balance.by_account =
880 Lib.TreeMap.from_List const
881 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
882 , ("B":|[], Amount.from_List [ Amount.usd $ -1 ])
883 ]
884 , Calc.Balance.by_unit =
885 Data.Map.fromList $
886 Data.List.map Calc.Balance.assoc_unit_sum $
887 [ Calc.Balance.Unit_Sum
888 { Calc.Balance.amount = Amount.usd $ 0
889 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
890 ["A":|[], "B":|[]]
891 }
892 ]
893 }
894 , "{A+$1 B, $+1}" ~: TestCase $
895 (@=?) True $
896 Calc.Balance.is_equilibrium_inferrable $
897 Calc.Balance.deviation $
898 Calc.Balance.Balance
899 { Calc.Balance.by_account =
900 Lib.TreeMap.from_List const
901 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
902 , ("B":|[], Amount.from_List [])
903 ]
904 , Calc.Balance.by_unit =
905 Data.Map.fromList $
906 Data.List.map Calc.Balance.assoc_unit_sum $
907 [ Calc.Balance.Unit_Sum
908 { Calc.Balance.amount = Amount.usd $ 1
909 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
910 ["A":|[]]
911 }
912 ]
913 }
914 , "{A+$1 B+€1, $+1 €+1}" ~: TestCase $
915 (@=?) True $
916 Calc.Balance.is_equilibrium_inferrable $
917 Calc.Balance.deviation $
918 Calc.Balance.Balance
919 { Calc.Balance.by_account =
920 Lib.TreeMap.from_List const
921 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
922 , ("B":|[], Amount.from_List [ Amount.eur $ 1 ])
923 ]
924 , Calc.Balance.by_unit =
925 Data.Map.fromList $
926 Data.List.map Calc.Balance.assoc_unit_sum $
927 [ Calc.Balance.Unit_Sum
928 { Calc.Balance.amount = Amount.usd $ 1
929 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
930 ["A":|[]]
931 }
932 , Calc.Balance.Unit_Sum
933 { Calc.Balance.amount = Amount.eur $ 1
934 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
935 ["B":|[]]
936 }
937 ]
938 }
939 , "{A+$1 B-$1+€1, $+0 €+1}" ~: TestCase $
940 (@=?) True $
941 Calc.Balance.is_equilibrium_inferrable $
942 Calc.Balance.deviation $
943 Calc.Balance.Balance
944 { Calc.Balance.by_account =
945 Lib.TreeMap.from_List const
946 [ ("A":|[], Amount.from_List [ Amount.usd $ 1 ])
947 , ("B":|[], Amount.from_List [ Amount.usd $ -1, Amount.eur $ 1 ])
948 ]
949 , Calc.Balance.by_unit =
950 Data.Map.fromList $
951 Data.List.map Calc.Balance.assoc_unit_sum $
952 [ Calc.Balance.Unit_Sum
953 { Calc.Balance.amount = Amount.usd $ 0
954 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
955 ["A":|[], "B":|[]]
956 }
957 , Calc.Balance.Unit_Sum
958 { Calc.Balance.amount = Amount.eur $ 1
959 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
960 ["B":|[]]
961 }
962 ]
963 }
964 , "{A+$1+€2+£3 B-$1-€2-£3, $+0 €+0 £+0}" ~: TestCase $
965 (@=?) True $
966 Calc.Balance.is_equilibrium_inferrable $
967 Calc.Balance.deviation $
968 Calc.Balance.Balance
969 { Calc.Balance.by_account =
970 Lib.TreeMap.from_List const
971 [ ("A":|[], Amount.from_List [ Amount.usd $ 1, Amount.eur $ 2, Amount.gbp $ 3 ])
972 , ("B":|[], Amount.from_List [ Amount.usd $ -1, Amount.eur $ -2, Amount.gbp $ -3 ])
973 ]
974 , Calc.Balance.by_unit =
975 Data.Map.fromList $
976 Data.List.map Calc.Balance.assoc_unit_sum $
977 [ Calc.Balance.Unit_Sum
978 { Calc.Balance.amount = Amount.usd $ 0
979 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
980 ["A":|[], "B":|[]]
981 }
982 , Calc.Balance.Unit_Sum
983 { Calc.Balance.amount = Amount.eur $ 0
984 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
985 ["A":|[], "B":|[]]
986 }
987 , Calc.Balance.Unit_Sum
988 { Calc.Balance.amount = Amount.gbp $ 0
989 , Calc.Balance.accounts = Data.Map.fromList $ Data.List.map (,())
990 ["A":|[], "B":|[]]
991 }
992 ]
993 }
994 ]
995 , "infer_equilibrium" ~: TestList
996 [ "{A+$1 B}" ~:
997 (snd $ Calc.Balance.infer_equilibrium $
998 Posting.from_List
999 [ (Posting.nil ("A":|[]))
1000 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ] }
1001 , (Posting.nil ("B":|[]))
1002 { Posting.amounts=Amount.from_List [] }
1003 ])
1004 ~?=
1005 (Right $
1006 Posting.from_List
1007 [ (Posting.nil ("A":|[]))
1008 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ] }
1009 , (Posting.nil ("B":|[]))
1010 { Posting.amounts=Amount.from_List [ Amount.usd $ -1 ] }
1011 ])
1012 , "{A+$1 B-1€}" ~:
1013 (snd $ Calc.Balance.infer_equilibrium $
1014 Posting.from_List
1015 [ (Posting.nil ("A":|[]))
1016 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ] }
1017 , (Posting.nil ("B":|[]))
1018 { Posting.amounts=Amount.from_List [ Amount.eur $ -1 ] }
1019 ])
1020 ~?=
1021 (Right $
1022 Posting.from_List
1023 [ (Posting.nil ("A":|[]))
1024 { Posting.amounts=Amount.from_List [ Amount.eur $ 1 ] }
1025 , (Posting.nil ("A":|[]))
1026 { Posting.amounts=Amount.from_List [ Amount.usd $ 1] }
1027 , (Posting.nil ("B":|[]))
1028 { Posting.amounts=Amount.from_List [ Amount.usd $ -1 ] }
1029 , (Posting.nil ("B":|[]))
1030 { Posting.amounts=Amount.from_List [ Amount.eur $ -1 ] }
1031 ])
1032 , "{A+$1 B+$1}" ~:
1033 (snd $ Calc.Balance.infer_equilibrium $
1034 Posting.from_List
1035 [ (Posting.nil ("A":|[]))
1036 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ] }
1037 , (Posting.nil ("B":|[]))
1038 { Posting.amounts=Amount.from_List [ Amount.usd $ 1 ] }
1039 ])
1040 ~?=
1041 (Left
1042 [ Calc.Balance.Unit_Sum
1043 { Calc.Balance.amount = Amount.usd $ 2
1044 , Calc.Balance.accounts = Data.Map.fromList []}
1045 ])
1046 ]
1047 ]
1048 ]
1049 , "Format" ~: TestList
1050 [ "Ledger" ~: TestList
1051 [ "Read" ~: TestList
1052 [ "account_name" ~: TestList
1053 [ "\"\"" ~:
1054 (Data.Either.rights $
1055 [P.runParser
1056 (Format.Ledger.Read.account_name <* P.eof)
1057 () "" (""::Text)])
1058 ~?=
1059 []
1060 , "\"A\"" ~:
1061 (Data.Either.rights $
1062 [P.runParser
1063 (Format.Ledger.Read.account_name <* P.eof)
1064 () "" ("A"::Text)])
1065 ~?=
1066 ["A"]
1067 , "\"AA\"" ~:
1068 (Data.Either.rights $
1069 [P.runParser
1070 (Format.Ledger.Read.account_name <* P.eof)
1071 () "" ("AA"::Text)])
1072 ~?=
1073 ["AA"]
1074 , "\" \"" ~:
1075 (Data.Either.rights $
1076 [P.runParser
1077 (Format.Ledger.Read.account_name <* P.eof)
1078 () "" (" "::Text)])
1079 ~?=
1080 []
1081 , "\":\"" ~:
1082 (Data.Either.rights $
1083 [P.runParser
1084 (Format.Ledger.Read.account_name <* P.eof)
1085 () "" (":"::Text)])
1086 ~?=
1087 []
1088 , "\"A:\"" ~:
1089 (Data.Either.rights $
1090 [P.runParser
1091 (Format.Ledger.Read.account_name <* P.eof)
1092 () "" ("A:"::Text)])
1093 ~?=
1094 []
1095 , "\":A\"" ~:
1096 (Data.Either.rights $
1097 [P.runParser
1098 (Format.Ledger.Read.account_name <* P.eof)
1099 () "" (":A"::Text)])
1100 ~?=
1101 []
1102 , "\"A \"" ~:
1103 (Data.Either.rights $
1104 [P.runParser
1105 (Format.Ledger.Read.account_name <* P.eof)
1106 () "" ("A "::Text)])
1107 ~?=
1108 []
1109 , "\"A \"" ~:
1110 (Data.Either.rights $
1111 [P.runParser
1112 (Format.Ledger.Read.account_name)
1113 () "" ("A "::Text)])
1114 ~?=
1115 ["A"]
1116 , "\"A A\"" ~:
1117 (Data.Either.rights $
1118 [P.runParser
1119 (Format.Ledger.Read.account_name <* P.eof)
1120 () "" ("A A"::Text)])
1121 ~?=
1122 ["A A"]
1123 , "\"A \"" ~:
1124 (Data.Either.rights $
1125 [P.runParser
1126 (Format.Ledger.Read.account_name <* P.eof)
1127 () "" ("A "::Text)])
1128 ~?=
1129 []
1130 , "\"A \\n\"" ~:
1131 (Data.Either.rights $
1132 [P.runParser
1133 (Format.Ledger.Read.account_name <* P.eof)
1134 () "" ("A \n"::Text)])
1135 ~?=
1136 []
1137 , "\"(A)A\"" ~:
1138 (Data.Either.rights $
1139 [P.runParser
1140 (Format.Ledger.Read.account_name <* P.eof)
1141 () "" ("(A)A"::Text)])
1142 ~?=
1143 ["(A)A"]
1144 , "\"( )A\"" ~:
1145 (Data.Either.rights $
1146 [P.runParser
1147 (Format.Ledger.Read.account_name <* P.eof)
1148 () "" ("( )A"::Text)])
1149 ~?=
1150 ["( )A"]
1151 , "\"(A) A\"" ~:
1152 (Data.Either.rights $
1153 [P.runParser
1154 (Format.Ledger.Read.account_name <* P.eof)
1155 () "" ("(A) A"::Text)])
1156 ~?=
1157 ["(A) A"]
1158 , "\"[ ]A\"" ~:
1159 (Data.Either.rights $
1160 [P.runParser
1161 (Format.Ledger.Read.account_name <* P.eof)
1162 () "" ("[ ]A"::Text)])
1163 ~?=
1164 ["[ ]A"]
1165 , "\"(A) \"" ~:
1166 (Data.Either.rights $
1167 [P.runParser
1168 (Format.Ledger.Read.account_name <* P.eof)
1169 () "" ("(A) "::Text)])
1170 ~?=
1171 []
1172 , "\"(A)\"" ~:
1173 (Data.Either.rights $
1174 [P.runParser
1175 (Format.Ledger.Read.account_name <* P.eof)
1176 () "" ("(A)"::Text)])
1177 ~?=
1178 ["(A)"]
1179 , "\"A(A)\"" ~:
1180 (Data.Either.rights $
1181 [P.runParser
1182 (Format.Ledger.Read.account_name <* P.eof)
1183 () "" ("A(A)"::Text)])
1184 ~?=
1185 [("A(A)"::Text)]
1186 , "\"[A]A\"" ~:
1187 (Data.Either.rights $
1188 [P.runParser
1189 (Format.Ledger.Read.account_name <* P.eof)
1190 () "" ("[A]A"::Text)])
1191 ~?=
1192 ["[A]A"]
1193 , "\"[A] A\"" ~:
1194 (Data.Either.rights $
1195 [P.runParser
1196 (Format.Ledger.Read.account_name <* P.eof)
1197 () "" ("[A] A"::Text)])
1198 ~?=
1199 ["[A] A"]
1200 , "\"[A] \"" ~:
1201 (Data.Either.rights $
1202 [P.runParser
1203 (Format.Ledger.Read.account_name <* P.eof)
1204 () "" ("[A] "::Text)])
1205 ~?=
1206 []
1207 , "\"[A]\"" ~:
1208 (Data.Either.rights $
1209 [P.runParser
1210 (Format.Ledger.Read.account_name <* P.eof)
1211 () "" ("[A]"::Text)])
1212 ~?=
1213 ["[A]"]
1214 ]
1215 , "account" ~: TestList
1216 [ "\"\"" ~:
1217 (Data.Either.rights $
1218 [P.runParser
1219 (Format.Ledger.Read.account <* P.eof)
1220 () "" (""::Text)])
1221 ~?=
1222 []
1223 , "\"A\"" ~:
1224 (Data.Either.rights $
1225 [P.runParser
1226 (Format.Ledger.Read.account <* P.eof)
1227 () "" ("A"::Text)])
1228 ~?=
1229 ["A":|[]]
1230 , "\"A:\"" ~:
1231 (Data.Either.rights $
1232 [P.runParser
1233 (Format.Ledger.Read.account <* P.eof)
1234 () "" ("A:"::Text)])
1235 ~?=
1236 []
1237 , "\":A\"" ~:
1238 (Data.Either.rights $
1239 [P.runParser
1240 (Format.Ledger.Read.account <* P.eof)
1241 () "" (":A"::Text)])
1242 ~?=
1243 []
1244 , "\"A \"" ~:
1245 (Data.Either.rights $
1246 [P.runParser
1247 (Format.Ledger.Read.account <* P.eof)
1248 () "" ("A "::Text)])
1249 ~?=
1250 []
1251 , "\" A\"" ~:
1252 (Data.Either.rights $
1253 [P.runParser
1254 (Format.Ledger.Read.account <* P.eof)
1255 () "" (" A"::Text)])
1256 ~?=
1257 []
1258 , "\"A:B\"" ~:
1259 (Data.Either.rights $
1260 [P.runParser
1261 (Format.Ledger.Read.account <* P.eof)
1262 () "" ("A:B"::Text)])
1263 ~?=
1264 ["A":|["B"]]
1265 , "\"A:B:C\"" ~:
1266 (Data.Either.rights $
1267 [P.runParser
1268 (Format.Ledger.Read.account <* P.eof)
1269 () "" ("A:B:C"::Text)])
1270 ~?=
1271 ["A":|["B", "C"]]
1272 , "\"Aa:Bbb:Cccc\"" ~:
1273 (Data.Either.rights $
1274 [P.runParser
1275 (Format.Ledger.Read.account <* P.eof)
1276 () "" ("Aa:Bbb:Cccc"::Text)])
1277 ~?=
1278 ["Aa":|["Bbb", "Cccc"]]
1279 , "\"A a : B b b : C c c c\"" ~:
1280 (Data.Either.rights $
1281 [P.runParser
1282 (Format.Ledger.Read.account <* P.eof)
1283 () "" ("A a : B b b : C c c c"::Text)])
1284 ~?=
1285 ["A a ":|[" B b b ", " C c c c"]]
1286 , "\"A: :C\"" ~:
1287 (Data.Either.rights $
1288 [P.runParser
1289 (Format.Ledger.Read.account <* P.eof)
1290 () "" ("A: :C"::Text)])
1291 ~?=
1292 ["A":|[" ", "C"]]
1293 , "\"A::C\"" ~:
1294 (Data.Either.rights $
1295 [P.runParser
1296 (Format.Ledger.Read.account <* P.eof)
1297 () "" ("A::C"::Text)])
1298 ~?=
1299 []
1300 , "\"A:B:(C)\"" ~:
1301 (Data.Either.rights $
1302 [P.runParser
1303 (Format.Ledger.Read.account <* P.eof)
1304 () "" ("A:B:(C)"::Text)])
1305 ~?=
1306 ["A":|["B", "(C)"]]
1307 ]
1308 , "posting_type" ~: TestList
1309 [ "A" ~:
1310 Format.Ledger.Read.posting_type
1311 ("A":|[])
1312 ~?=
1313 (Posting.Type_Regular, "A":|[])
1314 , "(" ~:
1315 Format.Ledger.Read.posting_type
1316 ("(":|[])
1317 ~?=
1318 (Posting.Type_Regular, "(":|[])
1319 , ")" ~:
1320 Format.Ledger.Read.posting_type
1321 (")":|[])
1322 ~?=
1323 (Posting.Type_Regular, ")":|[])
1324 , "()" ~:
1325 Format.Ledger.Read.posting_type
1326 ("()":|[])
1327 ~?=
1328 (Posting.Type_Regular, "()":|[])
1329 , "( )" ~:
1330 Format.Ledger.Read.posting_type
1331 ("( )":|[])
1332 ~?=
1333 (Posting.Type_Regular, "( )":|[])
1334 , "(A)" ~:
1335 Format.Ledger.Read.posting_type
1336 ("(A)":|[])
1337 ~?=
1338 (Posting.Type_Virtual, "A":|[])
1339 , "(A:B:C)" ~:
1340 Format.Ledger.Read.posting_type
1341 ("(A":|["B", "C)"])
1342 ~?=
1343 (Posting.Type_Virtual, "A":|["B", "C"])
1344 , "A:B:C" ~:
1345 Format.Ledger.Read.posting_type
1346 ("A":|["B", "C"])
1347 ~?=
1348 (Posting.Type_Regular, "A":|["B", "C"])
1349 , "(A):B:C" ~:
1350 Format.Ledger.Read.posting_type
1351 ("(A)":|["B", "C"])
1352 ~?=
1353 (Posting.Type_Regular, "(A)":|["B", "C"])
1354 , "A:(B):C" ~:
1355 Format.Ledger.Read.posting_type
1356 ("A":|["(B)", "C"])
1357 ~?=
1358 (Posting.Type_Regular, "A":|["(B)", "C"])
1359 , "A:B:(C)" ~:
1360 Format.Ledger.Read.posting_type
1361 ("A":|["B", "(C)"])
1362 ~?=
1363 (Posting.Type_Regular, "A":|["B", "(C)"])
1364 , "[" ~:
1365 Format.Ledger.Read.posting_type
1366 ("[":|[])
1367 ~?=
1368 (Posting.Type_Regular, "[":|[])
1369 , "]" ~:
1370 Format.Ledger.Read.posting_type
1371 ("]":|[])
1372 ~?=
1373 (Posting.Type_Regular, "]":|[])
1374 , "[]" ~:
1375 Format.Ledger.Read.posting_type
1376 ("[]":|[])
1377 ~?=
1378 (Posting.Type_Regular, "[]":|[])
1379 , "[ ]" ~:
1380 Format.Ledger.Read.posting_type
1381 ("[ ]":|[])
1382 ~?=
1383 (Posting.Type_Regular, "[ ]":|[])
1384 , "[A]" ~:
1385 Format.Ledger.Read.posting_type
1386 ("[A]":|[])
1387 ~?=
1388 (Posting.Type_Virtual_Balanced, "A":|[])
1389 , "[A:B:C]" ~:
1390 Format.Ledger.Read.posting_type
1391 ("[A":|["B", "C]"])
1392 ~?=
1393 (Posting.Type_Virtual_Balanced, "A":|["B", "C"])
1394 , "A:B:C" ~:
1395 Format.Ledger.Read.posting_type
1396 ("A":|["B", "C"])
1397 ~?=
1398 (Posting.Type_Regular, "A":|["B", "C"])
1399 , "[A]:B:C" ~:
1400 Format.Ledger.Read.posting_type
1401 ("[A]":|["B", "C"])
1402 ~?=
1403 (Posting.Type_Regular, "[A]":|["B", "C"])
1404 , "A:[B]:C" ~:
1405 Format.Ledger.Read.posting_type
1406 ("A":|["[B]", "C"])
1407 ~?=
1408 (Posting.Type_Regular, "A":|["[B]", "C"])
1409 , "A:B:[C]" ~:
1410 Format.Ledger.Read.posting_type
1411 ("A":|["B", "[C]"])
1412 ~?=
1413 (Posting.Type_Regular, "A":|["B", "[C]"])
1414 ]
1415 , "amount" ~: TestList
1416 [ "\"\" = Left" ~:
1417 (Data.Either.rights $
1418 [P.runParser
1419 (Format.Ledger.Read.amount <* P.eof)
1420 () "" (""::Text)])
1421 ~?=
1422 []
1423 , "\"0\" = Right 0" ~:
1424 (Data.Either.rights $
1425 [P.runParser
1426 (Format.Ledger.Read.amount <* P.eof)
1427 () "" ("0"::Text)])
1428 ~?=
1429 [Amount.nil
1430 { Amount.quantity = Decimal 0 0
1431 }]
1432 , "\"00\" = Right 0" ~:
1433 (Data.Either.rights $
1434 [P.runParser
1435 (Format.Ledger.Read.amount <* P.eof)
1436 () "" ("00"::Text)])
1437 ~?=
1438 [Amount.nil
1439 { Amount.quantity = Decimal 0 0
1440 }]
1441 , "\"0.\" = Right 0." ~:
1442 (Data.Either.rights $
1443 [P.runParser
1444 (Format.Ledger.Read.amount <* P.eof)
1445 () "" ("0."::Text)])
1446 ~?=
1447 [Amount.nil
1448 { Amount.quantity = Decimal 0 0
1449 , Amount.style =
1450 Amount.Style.nil
1451 { Amount.Style.fractioning = Just '.'
1452 }
1453 }]
1454 , "\".0\" = Right 0.0" ~:
1455 (Data.Either.rights $
1456 [P.runParser
1457 (Format.Ledger.Read.amount <* P.eof)
1458 () "" (".0"::Text)])
1459 ~?=
1460 [Amount.nil
1461 { Amount.quantity = Decimal 0 0
1462 , Amount.style =
1463 Amount.Style.nil
1464 { Amount.Style.fractioning = Just '.'
1465 , Amount.Style.precision = 1
1466 }
1467 }]
1468 , "\"0,\" = Right 0," ~:
1469 (Data.Either.rights $
1470 [P.runParser
1471 (Format.Ledger.Read.amount <* P.eof)
1472 () "" ("0,"::Text)])
1473 ~?=
1474 [Amount.nil
1475 { Amount.quantity = Decimal 0 0
1476 , Amount.style =
1477 Amount.Style.nil
1478 { Amount.Style.fractioning = Just ','
1479 }
1480 }]
1481 , "\",0\" = Right 0,0" ~:
1482 (Data.Either.rights $
1483 [P.runParser
1484 (Format.Ledger.Read.amount <* P.eof)
1485 () "" (",0"::Text)])
1486 ~?=
1487 [Amount.nil
1488 { Amount.quantity = Decimal 0 0
1489 , Amount.style =
1490 Amount.Style.nil
1491 { Amount.Style.fractioning = Just ','
1492 , Amount.Style.precision = 1
1493 }
1494 }]
1495 , "\"0_\" = Left" ~:
1496 (Data.Either.rights $
1497 [P.runParser
1498 (Format.Ledger.Read.amount <* P.eof)
1499 () "" ("0_"::Text)])
1500 ~?=
1501 []
1502 , "\"_0\" = Left" ~:
1503 (Data.Either.rights $
1504 [P.runParser
1505 (Format.Ledger.Read.amount <* P.eof)
1506 () "" ("_0"::Text)])
1507 ~?=
1508 []
1509 , "\"0.0\" = Right 0.0" ~:
1510 (Data.Either.rights $
1511 [P.runParser
1512 (Format.Ledger.Read.amount <* P.eof)
1513 () "" ("0.0"::Text)])
1514 ~?=
1515 [Amount.nil
1516 { Amount.quantity = Decimal 0 0
1517 , Amount.style =
1518 Amount.Style.nil
1519 { Amount.Style.fractioning = Just '.'
1520 , Amount.Style.precision = 1
1521 }
1522 }]
1523 , "\"00.00\" = Right 0.00" ~:
1524 (Data.Either.rights $
1525 [P.runParser
1526 (Format.Ledger.Read.amount <* P.eof)
1527 () "" ("00.00"::Text)])
1528 ~?=
1529 [Amount.nil
1530 { Amount.quantity = Decimal 0 0
1531 , Amount.style =
1532 Amount.Style.nil
1533 { Amount.Style.fractioning = Just '.'
1534 , Amount.Style.precision = 2
1535 }
1536 }]
1537 , "\"0,0\" = Right 0,0" ~:
1538 (Data.Either.rights $
1539 [P.runParser
1540 (Format.Ledger.Read.amount <* P.eof)
1541 () "" ("0,0"::Text)])
1542 ~?=
1543 [Amount.nil
1544 { Amount.quantity = Decimal 0 0
1545 , Amount.style =
1546 Amount.Style.nil
1547 { Amount.Style.fractioning = Just ','
1548 , Amount.Style.precision = 1
1549 }
1550 }]
1551 , "\"00,00\" = Right 0,00" ~:
1552 (Data.Either.rights $
1553 [P.runParser
1554 (Format.Ledger.Read.amount <* P.eof)
1555 () "" ("00,00"::Text)])
1556 ~?=
1557 [Amount.nil
1558 { Amount.quantity = Decimal 0 0
1559 , Amount.style =
1560 Amount.Style.nil
1561 { Amount.Style.fractioning = Just ','
1562 , Amount.Style.precision = 2
1563 }
1564 }]
1565 , "\"0_0\" = Right 0" ~:
1566 (Data.Either.rights $
1567 [P.runParser
1568 (Format.Ledger.Read.amount <* P.eof)
1569 () "" ("0_0"::Text)])
1570 ~?=
1571 [Amount.nil
1572 { Amount.quantity = Decimal 0 0
1573 , Amount.style =
1574 Amount.Style.nil
1575 { Amount.Style.fractioning = Nothing
1576 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [1]
1577 , Amount.Style.precision = 0
1578 }
1579 }]
1580 , "\"00_00\" = Right 0" ~:
1581 (Data.Either.rights $
1582 [P.runParser
1583 (Format.Ledger.Read.amount <* P.eof)
1584 () "" ("00_00"::Text)])
1585 ~?=
1586 [Amount.nil
1587 { Amount.quantity = Decimal 0 0
1588 , Amount.style =
1589 Amount.Style.nil
1590 { Amount.Style.fractioning = Nothing
1591 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [2]
1592 , Amount.Style.precision = 0
1593 }
1594 }]
1595 , "\"0,000.00\" = Right 0,000.00" ~:
1596 (Data.Either.rights $
1597 [P.runParser
1598 (Format.Ledger.Read.amount <* P.eof)
1599 () "" ("0,000.00"::Text)])
1600 ~?=
1601 [Amount.nil
1602 { Amount.quantity = Decimal 0 0
1603 , Amount.style =
1604 Amount.Style.nil
1605 { Amount.Style.fractioning = Just '.'
1606 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
1607 , Amount.Style.precision = 2
1608 }
1609 }]
1610 , "\"0.000,00\" = Right 0.000,00" ~:
1611 (Data.Either.rights $
1612 [P.runParser
1613 (Format.Ledger.Read.amount)
1614 () "" ("0.000,00"::Text)])
1615 ~?=
1616 [Amount.nil
1617 { Amount.quantity = Decimal 0 0
1618 , Amount.style =
1619 Amount.Style.nil
1620 { Amount.Style.fractioning = Just ','
1621 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
1622 , Amount.Style.precision = 2
1623 }
1624 }]
1625 , "\"1,000.00\" = Right 1,000.00" ~:
1626 (Data.Either.rights $
1627 [P.runParser
1628 (Format.Ledger.Read.amount <* P.eof)
1629 () "" ("1,000.00"::Text)])
1630 ~?=
1631 [Amount.nil
1632 { Amount.quantity = Decimal 0 1000
1633 , Amount.style =
1634 Amount.Style.nil
1635 { Amount.Style.fractioning = Just '.'
1636 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
1637 , Amount.Style.precision = 2
1638 }
1639 }]
1640 , "\"1.000,00\" = Right 1.000,00" ~:
1641 (Data.Either.rights $
1642 [P.runParser
1643 (Format.Ledger.Read.amount)
1644 () "" ("1.000,00"::Text)])
1645 ~?=
1646 [Amount.nil
1647 { Amount.quantity = Decimal 0 1000
1648 , Amount.style =
1649 Amount.Style.nil
1650 { Amount.Style.fractioning = Just ','
1651 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
1652 , Amount.Style.precision = 2
1653 }
1654 }]
1655 , "\"1,000.00.\" = Left" ~:
1656 (Data.Either.rights $
1657 [P.runParser
1658 (Format.Ledger.Read.amount)
1659 () "" ("1,000.00."::Text)])
1660 ~?=
1661 []
1662 , "\"1.000,00,\" = Left" ~:
1663 (Data.Either.rights $
1664 [P.runParser
1665 (Format.Ledger.Read.amount)
1666 () "" ("1.000,00,"::Text)])
1667 ~?=
1668 []
1669 , "\"1,000.00_\" = Left" ~:
1670 (Data.Either.rights $
1671 [P.runParser
1672 (Format.Ledger.Read.amount)
1673 () "" ("1,000.00_"::Text)])
1674 ~?=
1675 []
1676 , "\"12\" = Right 12" ~:
1677 (Data.Either.rights $
1678 [P.runParser
1679 (Format.Ledger.Read.amount <* P.eof)
1680 () "" ("123"::Text)])
1681 ~?=
1682 [Amount.nil
1683 { Amount.quantity = Decimal 0 123
1684 }]
1685 , "\"1.2\" = Right 1.2" ~:
1686 (Data.Either.rights $
1687 [P.runParser
1688 (Format.Ledger.Read.amount <* P.eof)
1689 () "" ("1.2"::Text)])
1690 ~?=
1691 [Amount.nil
1692 { Amount.quantity = Decimal 1 12
1693 , Amount.style =
1694 Amount.Style.nil
1695 { Amount.Style.fractioning = Just '.'
1696 , Amount.Style.precision = 1
1697 }
1698 }]
1699 , "\"1,2\" = Right 1,2" ~:
1700 (Data.Either.rights $
1701 [P.runParser
1702 (Format.Ledger.Read.amount <* P.eof)
1703 () "" ("1,2"::Text)])
1704 ~?=
1705 [Amount.nil
1706 { Amount.quantity = Decimal 1 12
1707 , Amount.style =
1708 Amount.Style.nil
1709 { Amount.Style.fractioning = Just ','
1710 , Amount.Style.precision = 1
1711 }
1712 }]
1713 , "\"12.23\" = Right 12.23" ~:
1714 (Data.Either.rights $
1715 [P.runParser
1716 (Format.Ledger.Read.amount <* P.eof)
1717 () "" ("12.34"::Text)])
1718 ~?=
1719 [Amount.nil
1720 { Amount.quantity = Decimal 2 1234
1721 , Amount.style =
1722 Amount.Style.nil
1723 { Amount.Style.fractioning = Just '.'
1724 , Amount.Style.precision = 2
1725 }
1726 }]
1727 , "\"12,23\" = Right 12,23" ~:
1728 (Data.Either.rights $
1729 [P.runParser
1730 (Format.Ledger.Read.amount <* P.eof)
1731 () "" ("12,34"::Text)])
1732 ~?=
1733 [Amount.nil
1734 { Amount.quantity = Decimal 2 1234
1735 , Amount.style =
1736 Amount.Style.nil
1737 { Amount.Style.fractioning = Just ','
1738 , Amount.Style.precision = 2
1739 }
1740 }]
1741 , "\"1_2\" = Right 1_2" ~:
1742 (Data.Either.rights $
1743 [P.runParser
1744 (Format.Ledger.Read.amount <* P.eof)
1745 () "" ("1_2"::Text)])
1746 ~?=
1747 [Amount.nil
1748 { Amount.quantity = Decimal 0 12
1749 , Amount.style =
1750 Amount.Style.nil
1751 { Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [1]
1752 , Amount.Style.precision = 0
1753 }
1754 }]
1755 , "\"1_23\" = Right 1_23" ~:
1756 (Data.Either.rights $
1757 [P.runParser
1758 (Format.Ledger.Read.amount <* P.eof)
1759 () "" ("1_23"::Text)])
1760 ~?=
1761 [Amount.nil
1762 { Amount.quantity = Decimal 0 123
1763 , Amount.style =
1764 Amount.Style.nil
1765 { Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [2]
1766 , Amount.Style.precision = 0
1767 }
1768 }]
1769 , "\"1_23_456\" = Right 1_23_456" ~:
1770 (Data.Either.rights $
1771 [P.runParser
1772 (Format.Ledger.Read.amount <* P.eof)
1773 () "" ("1_23_456"::Text)])
1774 ~?=
1775 [Amount.nil
1776 { Amount.quantity = Decimal 0 123456
1777 , Amount.style =
1778 Amount.Style.nil
1779 { Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [3, 2]
1780 , Amount.Style.precision = 0
1781 }
1782 }]
1783 , "\"1_23_456.7890_12345_678901\" = Right 1_23_456.7890_12345_678901" ~:
1784 (Data.Either.rights $
1785 [P.runParser
1786 (Format.Ledger.Read.amount <* P.eof)
1787 () "" ("1_23_456.7890_12345_678901"::Text)])
1788 ~?=
1789 [Amount.nil
1790 { Amount.quantity = Decimal 15 123456789012345678901
1791 , Amount.style =
1792 Amount.Style.nil
1793 { Amount.Style.fractioning = Just '.'
1794 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [3, 2]
1795 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping '_' [4, 5, 6]
1796 , Amount.Style.precision = 15
1797 }
1798 }]
1799 , "\"123456_78901_2345.678_90_1\" = Right 123456_78901_2345.678_90_1" ~:
1800 (Data.Either.rights $
1801 [P.runParser
1802 (Format.Ledger.Read.amount <* P.eof)
1803 () "" ("123456_78901_2345.678_90_1"::Text)])
1804 ~?=
1805 [Amount.nil
1806 { Amount.quantity = Decimal 6 123456789012345678901
1807 , Amount.style =
1808 Amount.Style.nil
1809 { Amount.Style.fractioning = Just '.'
1810 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '_' [4, 5, 6]
1811 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping '_' [3, 2]
1812 , Amount.Style.precision = 6
1813 }
1814 }]
1815 , "\"$1\" = Right $1" ~:
1816 (Data.Either.rights $
1817 [P.runParser
1818 (Format.Ledger.Read.amount <* P.eof)
1819 () "" ("$1"::Text)])
1820 ~?=
1821 [Amount.nil
1822 { Amount.quantity = Decimal 0 1
1823 , Amount.style =
1824 Amount.Style.nil
1825 { Amount.Style.fractioning = Nothing
1826 , Amount.Style.grouping_integral = Nothing
1827 , Amount.Style.grouping_fractional = Nothing
1828 , Amount.Style.precision = 0
1829 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1830 , Amount.Style.unit_spaced = Just False
1831 }
1832 , Amount.unit = "$"
1833 }]
1834 , "\"1$\" = Right 1$" ~:
1835 (Data.Either.rights $
1836 [P.runParser
1837 (Format.Ledger.Read.amount <* P.eof)
1838 () "" ("1$"::Text)])
1839 ~?=
1840 [Amount.nil
1841 { Amount.quantity = Decimal 0 1
1842 , Amount.style =
1843 Amount.Style.nil
1844 { Amount.Style.fractioning = Nothing
1845 , Amount.Style.grouping_integral = Nothing
1846 , Amount.Style.grouping_fractional = Nothing
1847 , Amount.Style.precision = 0
1848 , Amount.Style.unit_side = Just Amount.Style.Side_Right
1849 , Amount.Style.unit_spaced = Just False
1850 }
1851 , Amount.unit = "$"
1852 }]
1853 , "\"$ 1\" = Right $ 1" ~:
1854 (Data.Either.rights $
1855 [P.runParser
1856 (Format.Ledger.Read.amount <* P.eof)
1857 () "" ("$ 1"::Text)])
1858 ~?=
1859 [Amount.nil
1860 { Amount.quantity = Decimal 0 1
1861 , Amount.style =
1862 Amount.Style.nil
1863 { Amount.Style.fractioning = Nothing
1864 , Amount.Style.grouping_integral = Nothing
1865 , Amount.Style.grouping_fractional = Nothing
1866 , Amount.Style.precision = 0
1867 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1868 , Amount.Style.unit_spaced = Just True
1869 }
1870 , Amount.unit = "$"
1871 }]
1872 , "\"1 $\" = Right 1 $" ~:
1873 (Data.Either.rights $
1874 [P.runParser
1875 (Format.Ledger.Read.amount <* P.eof)
1876 () "" ("1 $"::Text)])
1877 ~?=
1878 [Amount.nil
1879 { Amount.quantity = Decimal 0 1
1880 , Amount.style =
1881 Amount.Style.nil
1882 { Amount.Style.fractioning = Nothing
1883 , Amount.Style.grouping_integral = Nothing
1884 , Amount.Style.grouping_fractional = Nothing
1885 , Amount.Style.precision = 0
1886 , Amount.Style.unit_side = Just Amount.Style.Side_Right
1887 , Amount.Style.unit_spaced = Just True
1888 }
1889 , Amount.unit = "$"
1890 }]
1891 , "\"-$1\" = Right $-1" ~:
1892 (Data.Either.rights $
1893 [P.runParser
1894 (Format.Ledger.Read.amount <* P.eof)
1895 () "" ("-$1"::Text)])
1896 ~?=
1897 [Amount.nil
1898 { Amount.quantity = Decimal 0 (-1)
1899 , Amount.style =
1900 Amount.Style.nil
1901 { Amount.Style.fractioning = Nothing
1902 , Amount.Style.grouping_integral = Nothing
1903 , Amount.Style.grouping_fractional = Nothing
1904 , Amount.Style.precision = 0
1905 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1906 , Amount.Style.unit_spaced = Just False
1907 }
1908 , Amount.unit = "$"
1909 }]
1910 , "\"\\\"4 2\\\"1\" = Right \\\"4 2\\\"1" ~:
1911 (Data.Either.rights $
1912 [P.runParser
1913 (Format.Ledger.Read.amount <* P.eof)
1914 () "" ("\"4 2\"1"::Text)])
1915 ~?=
1916 [Amount.nil
1917 { Amount.quantity = Decimal 0 1
1918 , Amount.style =
1919 Amount.Style.nil
1920 { Amount.Style.fractioning = Nothing
1921 , Amount.Style.grouping_integral = Nothing
1922 , Amount.Style.grouping_fractional = Nothing
1923 , Amount.Style.precision = 0
1924 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1925 , Amount.Style.unit_spaced = Just False
1926 }
1927 , Amount.unit = "4 2"
1928 }]
1929 , "\"1\\\"4 2\\\"\" = Right 1\\\"4 2\\\"" ~:
1930 (Data.Either.rights $
1931 [P.runParser
1932 (Format.Ledger.Read.amount <* P.eof)
1933 () "" ("1\"4 2\""::Text)])
1934 ~?=
1935 [Amount.nil
1936 { Amount.quantity = Decimal 0 1
1937 , Amount.style =
1938 Amount.Style.nil
1939 { Amount.Style.fractioning = Nothing
1940 , Amount.Style.grouping_integral = Nothing
1941 , Amount.Style.grouping_fractional = Nothing
1942 , Amount.Style.precision = 0
1943 , Amount.Style.unit_side = Just Amount.Style.Side_Right
1944 , Amount.Style.unit_spaced = Just False
1945 }
1946 , Amount.unit = "4 2"
1947 }]
1948 , "\"$1.000,00\" = Right $1.000,00" ~:
1949 (Data.Either.rights $
1950 [P.runParser
1951 (Format.Ledger.Read.amount <* P.eof)
1952 () "" ("$1.000,00"::Text)])
1953 ~?=
1954 [Amount.nil
1955 { Amount.quantity = Decimal 0 1000
1956 , Amount.style =
1957 Amount.Style.nil
1958 { Amount.Style.fractioning = Just ','
1959 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
1960 , Amount.Style.grouping_fractional = Nothing
1961 , Amount.Style.precision = 2
1962 , Amount.Style.unit_side = Just Amount.Style.Side_Left
1963 , Amount.Style.unit_spaced = Just False
1964 }
1965 , Amount.unit = "$"
1966 }]
1967 , "\"1.000,00$\" = Right 1.000,00$" ~:
1968 (Data.Either.rights $
1969 [P.runParser
1970 (Format.Ledger.Read.amount <* P.eof)
1971 () "" ("1.000,00$"::Text)])
1972 ~?=
1973 [Amount.nil
1974 { Amount.quantity = Decimal 0 1000
1975 , Amount.style =
1976 Amount.Style.nil
1977 { Amount.Style.fractioning = Just ','
1978 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping '.' [3]
1979 , Amount.Style.grouping_fractional = Nothing
1980 , Amount.Style.precision = 2
1981 , Amount.Style.unit_side = Just Amount.Style.Side_Right
1982 , Amount.Style.unit_spaced = Just False
1983 }
1984 , Amount.unit = "$"
1985 }]
1986 ]
1987 , "comment" ~: TestList
1988 [ "; some comment = Right \" some comment\"" ~:
1989 (Data.Either.rights $
1990 [P.runParser
1991 (Format.Ledger.Read.comment <* P.eof)
1992 () "" ("; some comment"::Text)])
1993 ~?=
1994 [ " some comment" ]
1995 , "; some comment \\n = Right \" some comment \"" ~:
1996 (Data.Either.rights $
1997 [P.runParser
1998 (Format.Ledger.Read.comment <* P.newline <* P.eof)
1999 () "" ("; some comment \n"::Text)])
2000 ~?=
2001 [ " some comment " ]
2002 , "; some comment \\r\\n = Right \" some comment \"" ~:
2003 (Data.Either.rights $
2004 [P.runParser
2005 (Format.Ledger.Read.comment <* P.string "\r\n" <* P.eof)
2006 () "" ("; some comment \r\n"::Text)])
2007 ~?=
2008 [ " some comment " ]
2009 ]
2010 , "comments" ~: TestList
2011 [ "; some comment\\n ; some other comment = Right [\" some comment\", \" some other comment\"]" ~:
2012 (Data.Either.rights $
2013 [P.runParser
2014 (Format.Ledger.Read.comments <* P.eof)
2015 () "" ("; some comment\n ; some other comment"::Text)])
2016 ~?=
2017 [ [" some comment", " some other comment"] ]
2018 , "; some comment \\n = Right \" some comment \"" ~:
2019 (Data.Either.rights $
2020 [P.runParser
2021 (Format.Ledger.Read.comments <* P.string "\n" <* P.eof)
2022 () "" ("; some comment \n"::Text)])
2023 ~?=
2024 [ [" some comment "] ]
2025 ]
2026 , "date" ~: TestList
2027 [ "2000/01/01" ~:
2028 (Data.Either.rights $
2029 [P.runParser
2030 (Format.Ledger.Read.date Nothing <* P.eof)
2031 () "" ("2000/01/01"::Text)])
2032 ~?=
2033 [ Time.ZonedTime
2034 (Time.LocalTime
2035 (Time.fromGregorian 2000 01 01)
2036 (Time.TimeOfDay 0 0 0))
2037 (Time.utc)]
2038 , "2000/01/01 some text" ~:
2039 (Data.Either.rights $
2040 [P.runParser
2041 (Format.Ledger.Read.date Nothing)
2042 () "" ("2000/01/01 some text"::Text)])
2043 ~?=
2044 [ Time.ZonedTime
2045 (Time.LocalTime
2046 (Time.fromGregorian 2000 01 01)
2047 (Time.TimeOfDay 0 0 0))
2048 (Time.utc)]
2049 , "2000/01/01 12:34" ~:
2050 (Data.Either.rights $
2051 [P.runParser
2052 (Format.Ledger.Read.date Nothing <* P.eof)
2053 () "" ("2000/01/01 12:34"::Text)])
2054 ~?=
2055 [ Time.ZonedTime
2056 (Time.LocalTime
2057 (Time.fromGregorian 2000 01 01)
2058 (Time.TimeOfDay 12 34 0))
2059 (Time.utc)]
2060 , "2000/01/01 12:34:56" ~:
2061 (Data.Either.rights $
2062 [P.runParser
2063 (Format.Ledger.Read.date Nothing <* P.eof)
2064 () "" ("2000/01/01 12:34:56"::Text)])
2065 ~?=
2066 [ Time.ZonedTime
2067 (Time.LocalTime
2068 (Time.fromGregorian 2000 01 01)
2069 (Time.TimeOfDay 12 34 56))
2070 (Time.utc)]
2071 , "2000/01/01 12:34 CET" ~:
2072 (Data.Either.rights $
2073 [P.runParser
2074 (Format.Ledger.Read.date Nothing <* P.eof)
2075 () "" ("2000/01/01 12:34 CET"::Text)])
2076 ~?=
2077 [ Time.ZonedTime
2078 (Time.LocalTime
2079 (Time.fromGregorian 2000 01 01)
2080 (Time.TimeOfDay 12 34 0))
2081 (Time.TimeZone 60 True "CET")]
2082 , "2000/01/01 12:34 +0130" ~:
2083 (Data.Either.rights $
2084 [P.runParser
2085 (Format.Ledger.Read.date Nothing <* P.eof)
2086 () "" ("2000/01/01 12:34 +0130"::Text)])
2087 ~?=
2088 [ Time.ZonedTime
2089 (Time.LocalTime
2090 (Time.fromGregorian 2000 01 01)
2091 (Time.TimeOfDay 12 34 0))
2092 (Time.TimeZone 90 False "+0130")]
2093 , "2000/01/01 12:34:56 CET" ~:
2094 (Data.Either.rights $
2095 [P.runParser
2096 (Format.Ledger.Read.date Nothing <* P.eof)
2097 () "" ("2000/01/01 12:34:56 CET"::Text)])
2098 ~?=
2099 [ Time.ZonedTime
2100 (Time.LocalTime
2101 (Time.fromGregorian 2000 01 01)
2102 (Time.TimeOfDay 12 34 56))
2103 (Time.TimeZone 60 True "CET")]
2104 , "2001/02/29" ~:
2105 (Data.Either.rights $
2106 [P.runParser
2107 (Format.Ledger.Read.date Nothing <* P.eof)
2108 () "" ("2001/02/29"::Text)])
2109 ~?=
2110 []
2111 , "01/01" ~:
2112 (Data.Either.rights $
2113 [P.runParser
2114 (Format.Ledger.Read.date (Just 2000) <* P.eof)
2115 () "" ("01/01"::Text)])
2116 ~?=
2117 [ Time.ZonedTime
2118 (Time.LocalTime
2119 (Time.fromGregorian 2000 01 01)
2120 (Time.TimeOfDay 0 0 0))
2121 (Time.utc)]
2122 ]
2123 , "tag_value" ~: TestList
2124 [ "," ~:
2125 (Data.Either.rights $
2126 [P.runParser
2127 (Format.Ledger.Read.tag_value <* P.eof)
2128 () "" (","::Text)])
2129 ~?=
2130 [","]
2131 , ",\\n" ~:
2132 (Data.Either.rights $
2133 [P.runParser
2134 (Format.Ledger.Read.tag_value <* P.char '\n' <* P.eof)
2135 () "" (",\n"::Text)])
2136 ~?=
2137 [","]
2138 , ",x" ~:
2139 (Data.Either.rights $
2140 [P.runParser
2141 (Format.Ledger.Read.tag_value <* P.eof)
2142 () "" (",x"::Text)])
2143 ~?=
2144 [",x"]
2145 , ",x:" ~:
2146 (Data.Either.rights $
2147 [P.runParser
2148 (Format.Ledger.Read.tag_value <* P.string ",x:" <* P.eof)
2149 () "" (",x:"::Text)])
2150 ~?=
2151 [""]
2152 , "v, v, n:" ~:
2153 (Data.Either.rights $
2154 [P.runParser
2155 (Format.Ledger.Read.tag_value <* P.string ", n:" <* P.eof)
2156 () "" ("v, v, n:"::Text)])
2157 ~?=
2158 ["v, v"]
2159 ]
2160 , "tag" ~: TestList
2161 [ "Name:" ~:
2162 (Data.Either.rights $
2163 [P.runParser
2164 (Format.Ledger.Read.tag <* P.eof)
2165 () "" ("Name:"::Text)])
2166 ~?=
2167 [("Name", "")]
2168 , "Name:Value" ~:
2169 (Data.Either.rights $
2170 [P.runParser
2171 (Format.Ledger.Read.tag <* P.eof)
2172 () "" ("Name:Value"::Text)])
2173 ~?=
2174 [("Name", "Value")]
2175 , "Name:Value\\n" ~:
2176 (Data.Either.rights $
2177 [P.runParser
2178 (Format.Ledger.Read.tag <* P.string "\n" <* P.eof)
2179 () "" ("Name:Value\n"::Text)])
2180 ~?=
2181 [("Name", "Value")]
2182 , "Name:Val ue" ~:
2183 (Data.Either.rights $
2184 [P.runParser
2185 (Format.Ledger.Read.tag <* P.eof)
2186 () "" ("Name:Val ue"::Text)])
2187 ~?=
2188 [("Name", "Val ue")]
2189 , "Name:," ~:
2190 (Data.Either.rights $
2191 [P.runParser
2192 (Format.Ledger.Read.tag <* P.eof)
2193 () "" ("Name:,"::Text)])
2194 ~?=
2195 [("Name", ",")]
2196 , "Name:Val,ue" ~:
2197 (Data.Either.rights $
2198 [P.runParser
2199 (Format.Ledger.Read.tag <* P.eof)
2200 () "" ("Name:Val,ue"::Text)])
2201 ~?=
2202 [("Name", "Val,ue")]
2203 , "Name:Val,ue:" ~:
2204 (Data.Either.rights $
2205 [P.runParser
2206 (Format.Ledger.Read.tag <* P.string ",ue:" <* P.eof)
2207 () "" ("Name:Val,ue:"::Text)])
2208 ~?=
2209 [("Name", "Val")]
2210 ]
2211 , "tags" ~: TestList
2212 [ "Name:" ~:
2213 (Data.Either.rights $
2214 [P.runParser
2215 (Format.Ledger.Read.tags <* P.eof)
2216 () "" ("Name:"::Text)])
2217 ~?=
2218 [Data.Map.fromList
2219 [ ("Name", [""])
2220 ]
2221 ]
2222 , "Name:," ~:
2223 (Data.Either.rights $
2224 [P.runParser
2225 (Format.Ledger.Read.tags <* P.eof)
2226 () "" ("Name:,"::Text)])
2227 ~?=
2228 [Data.Map.fromList
2229 [ ("Name", [","])
2230 ]
2231 ]
2232 , "Name:,Name:" ~:
2233 (Data.Either.rights $
2234 [P.runParser
2235 (Format.Ledger.Read.tags <* P.eof)
2236 () "" ("Name:,Name:"::Text)])
2237 ~?=
2238 [Data.Map.fromList
2239 [ ("Name", ["", ""])
2240 ]
2241 ]
2242 , "Name:,Name2:" ~:
2243 (Data.Either.rights $
2244 [P.runParser
2245 (Format.Ledger.Read.tags <* P.eof)
2246 () "" ("Name:,Name2:"::Text)])
2247 ~?=
2248 [Data.Map.fromList
2249 [ ("Name", [""])
2250 , ("Name2", [""])
2251 ]
2252 ]
2253 , "Name: , Name2:" ~:
2254 (Data.Either.rights $
2255 [P.runParser
2256 (Format.Ledger.Read.tags <* P.eof)
2257 () "" ("Name: , Name2:"::Text)])
2258 ~?=
2259 [Data.Map.fromList
2260 [ ("Name", [" "])
2261 , ("Name2", [""])
2262 ]
2263 ]
2264 , "Name:,Name2:,Name3:" ~:
2265 (Data.Either.rights $
2266 [P.runParser
2267 (Format.Ledger.Read.tags <* P.eof)
2268 () "" ("Name:,Name2:,Name3:"::Text)])
2269 ~?=
2270 [Data.Map.fromList
2271 [ ("Name", [""])
2272 , ("Name2", [""])
2273 , ("Name3", [""])
2274 ]
2275 ]
2276 , "Name:Val ue,Name2:V a l u e,Name3:V al ue" ~:
2277 (Data.Either.rights $
2278 [P.runParser
2279 (Format.Ledger.Read.tags <* P.eof)
2280 () "" ("Name:Val ue,Name2:V a l u e,Name3:V al ue"::Text)])
2281 ~?=
2282 [Data.Map.fromList
2283 [ ("Name", ["Val ue"])
2284 , ("Name2", ["V a l u e"])
2285 , ("Name3", ["V al ue"])
2286 ]
2287 ]
2288 ]
2289 , "posting" ~: TestList
2290 [ " A:B:C = Right A:B:C" ~:
2291 (Data.Either.rights $
2292 [P.runParser
2293 (Format.Ledger.Read.posting <* P.eof)
2294 Format.Ledger.Read.nil_Context "" (" A:B:C"::Text)])
2295 ~?=
2296 [ ( (Posting.nil ("A":|["B", "C"]))
2297 { Posting.sourcepos = P.newPos "" 1 1
2298 }
2299 , Posting.Type_Regular
2300 )
2301 ]
2302 , " !A:B:C = Right !A:B:C" ~:
2303 (Data.List.map fst $
2304 Data.Either.rights $
2305 [P.runParser
2306 (Format.Ledger.Read.posting <* P.eof)
2307 Format.Ledger.Read.nil_Context "" (" !A:B:C"::Text)])
2308 ~?=
2309 [ (Posting.nil ("A":|["B", "C"]))
2310 { Posting.sourcepos = P.newPos "" 1 1
2311 , Posting.status = True
2312 }
2313 ]
2314 , " *A:B:C = Right *A:B:C" ~:
2315 (Data.List.map fst $
2316 Data.Either.rights $
2317 [P.runParser
2318 (Format.Ledger.Read.posting <* P.eof)
2319 Format.Ledger.Read.nil_Context "" (" *A:B:C"::Text)])
2320 ~?=
2321 [ (Posting.nil ("A":|["B", "C"]))
2322 { Posting.amounts = Data.Map.fromList []
2323 , Posting.comments = []
2324 , Posting.dates = []
2325 , Posting.status = True
2326 , Posting.sourcepos = P.newPos "" 1 1
2327 , Posting.tags = Data.Map.fromList []
2328 }
2329 ]
2330 , " A:B:C $1 = Right A:B:C $1" ~:
2331 (Data.List.map fst $
2332 Data.Either.rights $
2333 [P.runParser
2334 (Format.Ledger.Read.posting <* P.eof)
2335 Format.Ledger.Read.nil_Context "" (" A:B:C $1"::Text)])
2336 ~?=
2337 [ (Posting.nil ("A":|["B","C $1"]))
2338 { Posting.sourcepos = P.newPos "" 1 1
2339 }
2340 ]
2341 , " A:B:C $1 = Right A:B:C $1" ~:
2342 (Data.List.map fst $
2343 Data.Either.rights $
2344 [P.runParser
2345 (Format.Ledger.Read.posting <* P.eof)
2346 Format.Ledger.Read.nil_Context "" (" A:B:C $1"::Text)])
2347 ~?=
2348 [ (Posting.nil ("A":|["B", "C"]))
2349 { Posting.amounts = Data.Map.fromList
2350 [ ("$", Amount.nil
2351 { Amount.quantity = 1
2352 , Amount.style = Amount.Style.nil
2353 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2354 , Amount.Style.unit_spaced = Just False
2355 }
2356 , Amount.unit = "$"
2357 })
2358 ]
2359 , Posting.sourcepos = P.newPos "" 1 1
2360 }
2361 ]
2362 , " A:B:C $1 + 1€ = Right A:B:C $1 + 1€" ~:
2363 (Data.List.map fst $
2364 Data.Either.rights $
2365 [P.runParser
2366 (Format.Ledger.Read.posting <* P.eof)
2367 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1€"::Text)])
2368 ~?=
2369 [ (Posting.nil ("A":|["B", "C"]))
2370 { Posting.amounts = Data.Map.fromList
2371 [ ("$", Amount.nil
2372 { Amount.quantity = 1
2373 , Amount.style = Amount.Style.nil
2374 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2375 , Amount.Style.unit_spaced = Just False
2376 }
2377 , Amount.unit = "$"
2378 })
2379 , ("€", Amount.nil
2380 { Amount.quantity = 1
2381 , Amount.style = Amount.Style.nil
2382 { Amount.Style.unit_side = Just Amount.Style.Side_Right
2383 , Amount.Style.unit_spaced = Just False
2384 }
2385 , Amount.unit = "€"
2386 })
2387 ]
2388 , Posting.sourcepos = P.newPos "" 1 1
2389 }
2390 ]
2391 , " A:B:C $1 + 1$ = Right A:B:C $2" ~:
2392 (Data.List.map fst $
2393 Data.Either.rights $
2394 [P.runParser
2395 (Format.Ledger.Read.posting <* P.eof)
2396 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1$"::Text)])
2397 ~?=
2398 [ (Posting.nil ("A":|["B", "C"]))
2399 { Posting.amounts = Data.Map.fromList
2400 [ ("$", Amount.nil
2401 { Amount.quantity = 2
2402 , Amount.style = Amount.Style.nil
2403 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2404 , Amount.Style.unit_spaced = Just False
2405 }
2406 , Amount.unit = "$"
2407 })
2408 ]
2409 , Posting.sourcepos = P.newPos "" 1 1
2410 }
2411 ]
2412 , " A:B:C $1 + 1$ + 1$ = Right A:B:C $3" ~:
2413 (Data.List.map fst $
2414 Data.Either.rights $
2415 [P.runParser
2416 (Format.Ledger.Read.posting <* P.eof)
2417 Format.Ledger.Read.nil_Context "" (" A:B:C $1 + 1$ + 1$"::Text)])
2418 ~?=
2419 [ (Posting.nil ("A":|["B", "C"]))
2420 { Posting.amounts = Data.Map.fromList
2421 [ ("$", Amount.nil
2422 { Amount.quantity = 3
2423 , Amount.style = Amount.Style.nil
2424 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2425 , Amount.Style.unit_spaced = Just False
2426 }
2427 , Amount.unit = "$"
2428 })
2429 ]
2430 , Posting.sourcepos = P.newPos "" 1 1
2431 }
2432 ]
2433 , " A:B:C ; some comment = Right A:B:C ; some comment" ~:
2434 (Data.List.map fst $
2435 Data.Either.rights $
2436 [P.runParser
2437 (Format.Ledger.Read.posting <* P.eof)
2438 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment"::Text)])
2439 ~?=
2440 [ (Posting.nil ("A":|["B", "C"]))
2441 { Posting.amounts = Data.Map.fromList []
2442 , Posting.comments = [" some comment"]
2443 , Posting.sourcepos = P.newPos "" 1 1
2444 }
2445 ]
2446 , " A:B:C ; some comment\\n ; some other comment = Right A:B:C ; some comment\\n ; some other comment" ~:
2447 (Data.List.map fst $
2448 Data.Either.rights $
2449 [P.runParser
2450 (Format.Ledger.Read.posting <* P.eof)
2451 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment\n ; some other comment"::Text)])
2452 ~?=
2453 [ (Posting.nil ("A":|["B", "C"]))
2454 { Posting.amounts = Data.Map.fromList []
2455 , Posting.comments = [" some comment", " some other comment"]
2456 , Posting.sourcepos = P.newPos "" 1 1
2457 }
2458 ]
2459 , " A:B:C $1 ; some comment = Right A:B:C $1 ; some comment" ~:
2460 (Data.List.map fst $
2461 Data.Either.rights $
2462 [P.runParser
2463 (Format.Ledger.Read.posting)
2464 Format.Ledger.Read.nil_Context "" (" A:B:C $1 ; some comment"::Text)])
2465 ~?=
2466 [ (Posting.nil ("A":|["B", "C"]))
2467 { Posting.amounts = Data.Map.fromList
2468 [ ("$", Amount.nil
2469 { Amount.quantity = 1
2470 , Amount.style = Amount.Style.nil
2471 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2472 , Amount.Style.unit_spaced = Just False
2473 }
2474 , Amount.unit = "$"
2475 })
2476 ]
2477 , Posting.comments = [" some comment"]
2478 , Posting.sourcepos = P.newPos "" 1 1
2479 }
2480 ]
2481 , " A:B:C ; N:V = Right A:B:C ; N:V" ~:
2482 (Data.List.map fst $
2483 Data.Either.rights $
2484 [P.runParser
2485 (Format.Ledger.Read.posting <* P.eof)
2486 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V"::Text)])
2487 ~?=
2488 [ (Posting.nil ("A":|["B", "C"]))
2489 { Posting.comments = [" N:V"]
2490 , Posting.sourcepos = P.newPos "" 1 1
2491 , Posting.tags = Data.Map.fromList
2492 [ ("N", ["V"])
2493 ]
2494 }
2495 ]
2496 , " A:B:C ; some comment N:V = Right A:B:C ; some comment N:V" ~:
2497 (Data.List.map fst $
2498 Data.Either.rights $
2499 [P.runParser
2500 (Format.Ledger.Read.posting <* P.eof)
2501 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment N:V"::Text)])
2502 ~?=
2503 [ (Posting.nil ("A":|["B", "C"]))
2504 { Posting.comments = [" some comment N:V"]
2505 , Posting.sourcepos = P.newPos "" 1 1
2506 , Posting.tags = Data.Map.fromList
2507 [ ("N", ["V"])
2508 ]
2509 }
2510 ]
2511 , " A:B:C ; some comment N:V v, N2:V2 v2 = Right A:B:C ; some comment N:V v, N2:V2 v2" ~:
2512 (Data.List.map fst $
2513 Data.Either.rights $
2514 [P.runParser
2515 (Format.Ledger.Read.posting )
2516 Format.Ledger.Read.nil_Context "" (" A:B:C ; some comment N:V v, N2:V2 v2"::Text)])
2517 ~?=
2518 [ (Posting.nil ("A":|["B", "C"]))
2519 { Posting.comments = [" some comment N:V v, N2:V2 v2"]
2520 , Posting.sourcepos = P.newPos "" 1 1
2521 , Posting.tags = Data.Map.fromList
2522 [ ("N", ["V v"])
2523 , ("N2", ["V2 v2"])
2524 ]
2525 }
2526 ]
2527 , " A:B:C ; N:V\\n ; N:V2 = Right A:B:C ; N:V\\n ; N:V2" ~:
2528 (Data.List.map fst $
2529 Data.Either.rights $
2530 [P.runParser
2531 (Format.Ledger.Read.posting <* P.eof)
2532 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V\n ; N:V2"::Text)])
2533 ~?=
2534 [ (Posting.nil ("A":|["B", "C"]))
2535 { Posting.comments = [" N:V", " N:V2"]
2536 , Posting.sourcepos = P.newPos "" 1 1
2537 , Posting.tags = Data.Map.fromList
2538 [ ("N", ["V", "V2"])
2539 ]
2540 }
2541 ]
2542 , " A:B:C ; N:V\\n ; N2:V = Right A:B:C ; N:V\\n ; N2:V" ~:
2543 (Data.List.map fst $
2544 Data.Either.rights $
2545 [P.runParser
2546 (Format.Ledger.Read.posting <* P.eof)
2547 Format.Ledger.Read.nil_Context "" (" A:B:C ; N:V\n ; N2:V"::Text)])
2548 ~?=
2549 [ (Posting.nil ("A":|["B", "C"]))
2550 { Posting.comments = [" N:V", " N2:V"]
2551 , Posting.sourcepos = P.newPos "" 1 1
2552 , Posting.tags = Data.Map.fromList
2553 [ ("N", ["V"])
2554 , ("N2", ["V"])
2555 ]
2556 }
2557 ]
2558 , " A:B:C ; date:2001/01/01 = Right A:B:C ; date:2001/01/01" ~:
2559 (Data.List.map fst $
2560 Data.Either.rights $
2561 [P.runParser
2562 (Format.Ledger.Read.posting <* P.eof)
2563 Format.Ledger.Read.nil_Context "" (" A:B:C ; date:2001/01/01"::Text)])
2564 ~?=
2565 [ (Posting.nil ("A":|["B", "C"]))
2566 { Posting.comments = [" date:2001/01/01"]
2567 , Posting.dates =
2568 [ Time.ZonedTime
2569 (Time.LocalTime
2570 (Time.fromGregorian 2001 01 01)
2571 (Time.TimeOfDay 0 0 0))
2572 Time.utc
2573 ]
2574 , Posting.sourcepos = P.newPos "" 1 1
2575 , Posting.tags = Data.Map.fromList
2576 [ ("date", ["2001/01/01"])
2577 ]
2578 }
2579 ]
2580 , " (A:B:C) = Right (A:B:C)" ~:
2581 (Data.Either.rights $
2582 [P.runParser
2583 (Format.Ledger.Read.posting <* P.eof)
2584 Format.Ledger.Read.nil_Context "" (" (A:B:C)"::Text)])
2585 ~?=
2586 [ ( (Posting.nil ("A":|["B", "C"]))
2587 { Posting.sourcepos = P.newPos "" 1 1
2588 }
2589 , Posting.Type_Virtual
2590 )
2591 ]
2592 , " [A:B:C] = Right [A:B:C]" ~:
2593 (Data.Either.rights $
2594 [P.runParser
2595 (Format.Ledger.Read.posting <* P.eof)
2596 Format.Ledger.Read.nil_Context "" (" [A:B:C]"::Text)])
2597 ~?=
2598 [ ( (Posting.nil ("A":|["B", "C"]))
2599 { Posting.sourcepos = P.newPos "" 1 1
2600 }
2601 , Posting.Type_Virtual_Balanced
2602 )
2603 ]
2604 ]
2605 , "transaction" ~: TestList
2606 [ "2000/01/01 some description\\n A:B:C $1\\n a:b:c" ~:
2607 (Data.Either.rights $
2608 [P.runParser_with_Error
2609 (Format.Ledger.Read.transaction <* P.eof)
2610 Format.Ledger.Read.nil_Context "" ("2000/01/01 some description\n A:B:C $1\n a:b:c"::Text)])
2611 ~?=
2612 [ Transaction.nil
2613 { Transaction.dates=
2614 ( Time.ZonedTime
2615 (Time.LocalTime
2616 (Time.fromGregorian 2000 01 01)
2617 (Time.TimeOfDay 0 0 0))
2618 (Time.utc)
2619 , [] )
2620 , Transaction.description="some description"
2621 , Transaction.postings = Posting.from_List
2622 [ (Posting.nil ("A":|["B", "C"]))
2623 { Posting.amounts = Data.Map.fromList
2624 [ ("$", Amount.nil
2625 { Amount.quantity = 1
2626 , Amount.style = Amount.Style.nil
2627 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2628 , Amount.Style.unit_spaced = Just False
2629 }
2630 , Amount.unit = "$"
2631 })
2632 ]
2633 , Posting.sourcepos = P.newPos "" 2 1
2634 }
2635 , (Posting.nil ("a":|["b", "c"]))
2636 { Posting.sourcepos = P.newPos "" 3 1
2637 }
2638 ]
2639 , Transaction.sourcepos = P.newPos "" 1 1
2640 }
2641 ]
2642 , "2000/01/01 some description\\n A:B:C $1\\n a:b:c\\n" ~:
2643 (Data.Either.rights $
2644 [P.runParser_with_Error
2645 (Format.Ledger.Read.transaction <* P.newline <* P.eof)
2646 Format.Ledger.Read.nil_Context "" ("2000/01/01 some description\n A:B:C $1\n a:b:c\n"::Text)])
2647 ~?=
2648 [ Transaction.nil
2649 { Transaction.dates=
2650 ( Time.ZonedTime
2651 (Time.LocalTime
2652 (Time.fromGregorian 2000 01 01)
2653 (Time.TimeOfDay 0 0 0))
2654 (Time.utc)
2655 , [] )
2656 , Transaction.description="some description"
2657 , Transaction.postings = Posting.from_List
2658 [ (Posting.nil ("A":|["B", "C"]))
2659 { Posting.amounts = Data.Map.fromList
2660 [ ("$", Amount.nil
2661 { Amount.quantity = 1
2662 , Amount.style = Amount.Style.nil
2663 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2664 , Amount.Style.unit_spaced = Just False
2665 }
2666 , Amount.unit = "$"
2667 })
2668 ]
2669 , Posting.sourcepos = P.newPos "" 2 1
2670 }
2671 , (Posting.nil ("a":|["b", "c"]))
2672 { Posting.sourcepos = P.newPos "" 3 1
2673 }
2674 ]
2675 , Transaction.sourcepos = P.newPos "" 1 1
2676 }
2677 ]
2678 , "2000/01/01 some description ; some comment\\n ; some other;comment\\n ; some Tag:\\n ; some last comment\\n A:B:C $1\\n a:b:c" ~:
2679 (Data.Either.rights $
2680 [P.runParser_with_Error
2681 (Format.Ledger.Read.transaction <* P.eof)
2682 Format.Ledger.Read.nil_Context "" ("2000/01/01 some description ; some comment\n ; some other;comment\n ; some Tag:\n ; some last comment\n A:B:C $1\n a:b:c"::Text)])
2683 ~?=
2684 [ Transaction.nil
2685 { Transaction.comments_after =
2686 [ " some comment"
2687 , " some other;comment"
2688 , " some Tag:"
2689 , " some last comment"
2690 ]
2691 , Transaction.dates=
2692 ( Time.ZonedTime
2693 (Time.LocalTime
2694 (Time.fromGregorian 2000 01 01)
2695 (Time.TimeOfDay 0 0 0))
2696 (Time.utc)
2697 , [] )
2698 , Transaction.description="some description"
2699 , Transaction.postings = Posting.from_List
2700 [ (Posting.nil ("A":|["B", "C"]))
2701 { Posting.amounts = Data.Map.fromList
2702 [ ("$", Amount.nil
2703 { Amount.quantity = 1
2704 , Amount.style = Amount.Style.nil
2705 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2706 , Amount.Style.unit_spaced = Just False
2707 }
2708 , Amount.unit = "$"
2709 })
2710 ]
2711 , Posting.sourcepos = P.newPos "" 5 1
2712 }
2713 , (Posting.nil ("a":|["b", "c"]))
2714 { Posting.sourcepos = P.newPos "" 6 1
2715 , Posting.tags = Data.Map.fromList []
2716 }
2717 ]
2718 , Transaction.sourcepos = P.newPos "" 1 1
2719 , Transaction.tags = Data.Map.fromList
2720 [ ("Tag", [""])
2721 ]
2722 }
2723 ]
2724 ]
2725 , "journal" ~: TestList
2726 [ "2000/01/01 1° description\\n A:B:C $1\\n a:b:c\\n2000/01/02 2° description\\n A:B:C $1\\n x:y:z" ~: TestCase $ do
2727 jnl <- liftIO $
2728 P.runParserT_with_Error
2729 (Format.Ledger.Read.journal "" {-<* P.eof-})
2730 Format.Ledger.Read.nil_Context "" ("2000/01/01 1° description\n A:B:C $1\n a:b:c\n2000/01/02 2° description\n A:B:C $1\n x:y:z"::Text)
2731 (Data.List.map
2732 (\j -> j{Format.Ledger.Journal.last_read_time=
2733 Format.Ledger.Journal.last_read_time Format.Ledger.Journal.nil}) $
2734 Data.Either.rights [jnl])
2735 @?=
2736 [ Format.Ledger.Journal.nil
2737 { Format.Ledger.Journal.transactions = Transaction.from_List
2738 [ Transaction.nil
2739 { Transaction.dates=
2740 ( Time.ZonedTime
2741 (Time.LocalTime
2742 (Time.fromGregorian 2000 01 01)
2743 (Time.TimeOfDay 0 0 0))
2744 (Time.utc)
2745 , [] )
2746 , Transaction.description="1° description"
2747 , Transaction.postings = Posting.from_List
2748 [ (Posting.nil ("A":|["B", "C"]))
2749 { Posting.amounts = Data.Map.fromList
2750 [ ("$", Amount.nil
2751 { Amount.quantity = 1
2752 , Amount.style = Amount.Style.nil
2753 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2754 , Amount.Style.unit_spaced = Just False
2755 }
2756 , Amount.unit = "$"
2757 })
2758 ]
2759 , Posting.sourcepos = P.newPos "" 2 1
2760 }
2761 , (Posting.nil ("a":|["b", "c"]))
2762 { Posting.sourcepos = P.newPos "" 3 1
2763 }
2764 ]
2765 , Transaction.sourcepos = P.newPos "" 1 1
2766 }
2767 , Transaction.nil
2768 { Transaction.dates=
2769 ( Time.ZonedTime
2770 (Time.LocalTime
2771 (Time.fromGregorian 2000 01 02)
2772 (Time.TimeOfDay 0 0 0))
2773 (Time.utc)
2774 , [] )
2775 , Transaction.description="2° description"
2776 , Transaction.postings = Posting.from_List
2777 [ (Posting.nil ("A":|["B", "C"]))
2778 { Posting.amounts = Data.Map.fromList
2779 [ ("$", Amount.nil
2780 { Amount.quantity = 1
2781 , Amount.style = Amount.Style.nil
2782 { Amount.Style.unit_side = Just Amount.Style.Side_Left
2783 , Amount.Style.unit_spaced = Just False
2784 }
2785 , Amount.unit = "$"
2786 })
2787 ]
2788 , Posting.sourcepos = P.newPos "" 5 1
2789 }
2790 , (Posting.nil ("x":|["y", "z"]))
2791 { Posting.sourcepos = P.newPos "" 6 1
2792 }
2793 ]
2794 , Transaction.sourcepos = P.newPos "" 4 1
2795 }
2796 ]
2797 }
2798 ]
2799 ]
2800 ]
2801 , "Write" ~: TestList
2802 [ "account" ~: TestList
2803 [ "A" ~:
2804 ((Format.Ledger.Write.show False $
2805 Format.Ledger.Write.account Posting.Type_Regular $
2806 "A":|[])
2807 ~?=
2808 "A")
2809 , "A:B:C" ~:
2810 ((Format.Ledger.Write.show False $
2811 Format.Ledger.Write.account Posting.Type_Regular $
2812 "A":|["B", "C"])
2813 ~?=
2814 "A:B:C")
2815 , "(A:B:C)" ~:
2816 ((Format.Ledger.Write.show False $
2817 Format.Ledger.Write.account Posting.Type_Virtual $
2818 "A":|["B", "C"])
2819 ~?=
2820 "(A:B:C)")
2821 , "[A:B:C]" ~:
2822 ((Format.Ledger.Write.show False $
2823 Format.Ledger.Write.account Posting.Type_Virtual_Balanced $
2824 "A":|["B", "C"])
2825 ~?=
2826 "[A:B:C]")
2827 ]
2828 , "amount" ~: TestList
2829 [ "nil" ~:
2830 ((Format.Ledger.Write.show False $
2831 Format.Ledger.Write.amount
2832 Amount.nil)
2833 ~?=
2834 "0")
2835 , "nil @ prec=2" ~:
2836 ((Format.Ledger.Write.show False $
2837 Format.Ledger.Write.amount
2838 Amount.nil
2839 { Amount.style = Amount.Style.nil
2840 { Amount.Style.precision = 2 }
2841 })
2842 ~?=
2843 "0.00")
2844 , "123" ~:
2845 ((Format.Ledger.Write.show False $
2846 Format.Ledger.Write.amount
2847 Amount.nil
2848 { Amount.quantity = Decimal 0 123
2849 })
2850 ~?=
2851 "123")
2852 , "-123" ~:
2853 ((Format.Ledger.Write.show False $
2854 Format.Ledger.Write.amount
2855 Amount.nil
2856 { Amount.quantity = Decimal 0 (- 123)
2857 })
2858 ~?=
2859 "-123")
2860 , "12.3 @ prec=0" ~:
2861 ((Format.Ledger.Write.show False $
2862 Format.Ledger.Write.amount
2863 Amount.nil
2864 { Amount.quantity = Decimal 1 123
2865 , Amount.style = Amount.Style.nil
2866 { Amount.Style.fractioning = Just '.'
2867 }
2868 })
2869 ~?=
2870 "12")
2871 , "12.5 @ prec=0" ~:
2872 ((Format.Ledger.Write.show False $
2873 Format.Ledger.Write.amount
2874 Amount.nil
2875 { Amount.quantity = Decimal 1 125
2876 , Amount.style = Amount.Style.nil
2877 { Amount.Style.fractioning = Just '.'
2878 }
2879 })
2880 ~?=
2881 "13")
2882 , "12.3 @ prec=1" ~:
2883 ((Format.Ledger.Write.show False $
2884 Format.Ledger.Write.amount
2885 Amount.nil
2886 { Amount.quantity = Decimal 1 123
2887 , Amount.style = Amount.Style.nil
2888 { Amount.Style.fractioning = Just '.'
2889 , Amount.Style.precision = 1
2890 }
2891 })
2892 ~?=
2893 "12.3")
2894 , "1,234.56 @ prec=2" ~:
2895 ((Format.Ledger.Write.show False $
2896 Format.Ledger.Write.amount
2897 Amount.nil
2898 { Amount.quantity = Decimal 2 123456
2899 , Amount.style = Amount.Style.nil
2900 { Amount.Style.fractioning = Just '.'
2901 , Amount.Style.precision = 2
2902 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
2903 }
2904 })
2905 ~?=
2906 "1,234.56")
2907 , "123,456,789,01,2.3456789 @ prec=7" ~:
2908 ((Format.Ledger.Write.show False $
2909 Format.Ledger.Write.amount
2910 Amount.nil
2911 { Amount.quantity = Decimal 7 1234567890123456789
2912 , Amount.style = Amount.Style.nil
2913 { Amount.Style.fractioning = Just '.'
2914 , Amount.Style.precision = 7
2915 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [1, 2, 3]
2916 }
2917 })
2918 ~?=
2919 "123,456,789,01,2.3456789")
2920 , "1234567.8,90,123,456,789 @ prec=12" ~:
2921 ((Format.Ledger.Write.show False $
2922 Format.Ledger.Write.amount
2923 Amount.nil
2924 { Amount.quantity = Decimal 12 1234567890123456789
2925 , Amount.style = Amount.Style.nil
2926 { Amount.Style.fractioning = Just '.'
2927 , Amount.Style.precision = 12
2928 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [1, 2, 3]
2929 }
2930 })
2931 ~?=
2932 "1234567.8,90,123,456,789")
2933 , "1,2,3,4,5,6,7,89,012.3456789 @ prec=7" ~:
2934 ((Format.Ledger.Write.show False $
2935 Format.Ledger.Write.amount
2936 Amount.nil
2937 { Amount.quantity = Decimal 7 1234567890123456789
2938 , Amount.style = Amount.Style.nil
2939 { Amount.Style.fractioning = Just '.'
2940 , Amount.Style.precision = 7
2941 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3, 2, 1]
2942 }
2943 })
2944 ~?=
2945 "1,2,3,4,5,6,7,89,012.3456789")
2946 , "1234567.890,12,3,4,5,6,7,8,9 @ prec=12" ~:
2947 ((Format.Ledger.Write.show False $
2948 Format.Ledger.Write.amount
2949 Amount.nil
2950 { Amount.quantity = Decimal 12 1234567890123456789
2951 , Amount.style = Amount.Style.nil
2952 { Amount.Style.fractioning = Just '.'
2953 , Amount.Style.precision = 12
2954 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [3, 2, 1]
2955 }
2956 })
2957 ~?=
2958 "1234567.890,12,3,4,5,6,7,8,9")
2959 ]
2960 , "amount_length" ~: TestList
2961 [ "nil" ~:
2962 ((Format.Ledger.Write.amount_length
2963 Amount.nil)
2964 ~?=
2965 1)
2966 , "nil @ prec=2" ~:
2967 ((Format.Ledger.Write.amount_length
2968 Amount.nil
2969 { Amount.style = Amount.Style.nil
2970 { Amount.Style.precision = 2 }
2971 })
2972 ~?=
2973 4)
2974 , "123" ~:
2975 ((Format.Ledger.Write.amount_length
2976 Amount.nil
2977 { Amount.quantity = Decimal 0 123
2978 })
2979 ~?=
2980 3)
2981 , "-123" ~:
2982 ((Format.Ledger.Write.amount_length
2983 Amount.nil
2984 { Amount.quantity = Decimal 0 (- 123)
2985 })
2986 ~?=
2987 4)
2988 , "12.3 @ prec=0" ~:
2989 ((Format.Ledger.Write.amount_length
2990 Amount.nil
2991 { Amount.quantity = Decimal 1 123
2992 , Amount.style = Amount.Style.nil
2993 { Amount.Style.fractioning = Just '.'
2994 }
2995 })
2996 ~?=
2997 2)
2998 , "12.5 @ prec=0" ~:
2999 ((Format.Ledger.Write.amount_length
3000 Amount.nil
3001 { Amount.quantity = Decimal 1 125
3002 , Amount.style = Amount.Style.nil
3003 { Amount.Style.fractioning = Just '.'
3004 }
3005 })
3006 ~?=
3007 2)
3008 , "12.3 @ prec=1" ~:
3009 ((Format.Ledger.Write.amount_length
3010 Amount.nil
3011 { Amount.quantity = Decimal 1 123
3012 , Amount.style = Amount.Style.nil
3013 { Amount.Style.fractioning = Just '.'
3014 , Amount.Style.precision = 1
3015 }
3016 })
3017 ~?=
3018 4)
3019 , "1,234.56 @ prec=2" ~:
3020 ((Format.Ledger.Write.amount_length
3021 Amount.nil
3022 { Amount.quantity = Decimal 2 123456
3023 , Amount.style = Amount.Style.nil
3024 { Amount.Style.fractioning = Just '.'
3025 , Amount.Style.precision = 2
3026 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3]
3027 }
3028 })
3029 ~?=
3030 8)
3031 , "123,456,789,01,2.3456789 @ prec=7" ~:
3032 ((Format.Ledger.Write.amount_length
3033 Amount.nil
3034 { Amount.quantity = Decimal 7 1234567890123456789
3035 , Amount.style = Amount.Style.nil
3036 { Amount.Style.fractioning = Just '.'
3037 , Amount.Style.precision = 7
3038 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [1, 2, 3]
3039 }
3040 })
3041 ~?=
3042 24)
3043 , "1234567.8,90,123,456,789 @ prec=12" ~:
3044 ((Format.Ledger.Write.amount_length
3045 Amount.nil
3046 { Amount.quantity = Decimal 12 1234567890123456789
3047 , Amount.style = Amount.Style.nil
3048 { Amount.Style.fractioning = Just '.'
3049 , Amount.Style.precision = 12
3050 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [1, 2, 3]
3051 }
3052 })
3053 ~?=
3054 24)
3055 , "1,2,3,4,5,6,7,89,012.3456789 @ prec=7" ~:
3056 ((Format.Ledger.Write.amount_length
3057 Amount.nil
3058 { Amount.quantity = Decimal 7 1234567890123456789
3059 , Amount.style = Amount.Style.nil
3060 { Amount.Style.fractioning = Just '.'
3061 , Amount.Style.precision = 7
3062 , Amount.Style.grouping_integral = Just $ Amount.Style.Grouping ',' [3, 2, 1]
3063 }
3064 })
3065 ~?=
3066 28)
3067 , "1234567.890,12,3,4,5,6,7,8,9 @ prec=12" ~:
3068 ((Format.Ledger.Write.amount_length
3069 Amount.nil
3070 { Amount.quantity = Decimal 12 1234567890123456789
3071 , Amount.style = Amount.Style.nil
3072 { Amount.Style.fractioning = Just '.'
3073 , Amount.Style.precision = 12
3074 , Amount.Style.grouping_fractional = Just $ Amount.Style.Grouping ',' [3, 2, 1]
3075 }
3076 })
3077 ~?=
3078 28)
3079 ]
3080 , "date" ~: TestList
3081 [ "nil" ~:
3082 ((Format.Ledger.Write.show False $
3083 Format.Ledger.Write.date
3084 Date.nil)
3085 ~?=
3086 "1970/01/01")
3087 , "2000/01/01 12:34:51 CET" ~:
3088 (Format.Ledger.Write.show False $
3089 Format.Ledger.Write.date $
3090 Time.ZonedTime
3091 (Time.LocalTime
3092 (Time.fromGregorian 2000 01 01)
3093 (Time.TimeOfDay 12 34 51))
3094 (Time.TimeZone 60 False "CET"))
3095 ~?=
3096 "2000/01/01 12:34:51 CET"
3097 , "2000/01/01 12:34:51 +0100" ~:
3098 (Format.Ledger.Write.show False $
3099 Format.Ledger.Write.date $
3100 Time.ZonedTime
3101 (Time.LocalTime
3102 (Time.fromGregorian 2000 01 01)
3103 (Time.TimeOfDay 12 34 51))
3104 (Time.TimeZone 60 False ""))
3105 ~?=
3106 "2000/01/01 12:34:51 +0100"
3107 , "2000/01/01 01:02:03" ~:
3108 (Format.Ledger.Write.show False $
3109 Format.Ledger.Write.date $
3110 Time.ZonedTime
3111 (Time.LocalTime
3112 (Time.fromGregorian 2000 01 01)
3113 (Time.TimeOfDay 1 2 3))
3114 (Time.utc))
3115 ~?=
3116 "2000/01/01 01:02:03"
3117 , "01/01 01:02" ~:
3118 (Format.Ledger.Write.show False $
3119 Format.Ledger.Write.date $
3120 Time.ZonedTime
3121 (Time.LocalTime
3122 (Time.fromGregorian 0 01 01)
3123 (Time.TimeOfDay 1 2 0))
3124 (Time.utc))
3125 ~?=
3126 "01/01 01:02"
3127 , "01/01 01:00" ~:
3128 (Format.Ledger.Write.show False $
3129 Format.Ledger.Write.date $
3130 Time.ZonedTime
3131 (Time.LocalTime
3132 (Time.fromGregorian 0 01 01)
3133 (Time.TimeOfDay 1 0 0))
3134 (Time.utc))
3135 ~?=
3136 "01/01 01:00"
3137 , "01/01 00:01" ~:
3138 (Format.Ledger.Write.show False $
3139 Format.Ledger.Write.date $
3140 Time.ZonedTime
3141 (Time.LocalTime
3142 (Time.fromGregorian 0 01 01)
3143 (Time.TimeOfDay 0 1 0))
3144 (Time.utc))
3145 ~?=
3146 "01/01 00:01"
3147 , "01/01" ~:
3148 (Format.Ledger.Write.show False $
3149 Format.Ledger.Write.date $
3150 Time.ZonedTime
3151 (Time.LocalTime
3152 (Time.fromGregorian 0 01 01)
3153 (Time.TimeOfDay 0 0 0))
3154 (Time.utc))
3155 ~?=
3156 "01/01"
3157 ]
3158 , "transaction" ~: TestList
3159 [ "nil" ~:
3160 ((Format.Ledger.Write.show False $
3161 Format.Ledger.Write.transaction
3162 Transaction.nil)
3163 ~?=
3164 "1970/01/01\n")
3165 , "2000/01/01 some description\\n\\ta:b:c\\n\\t\\t; first comment\\n\\t\\t; second comment\\n\\t\\t; third comment\\n\\tA:B:C $1" ~:
3166 ((Format.Ledger.Write.show False $
3167 Format.Ledger.Write.transaction $
3168 Transaction.nil
3169 { Transaction.dates=
3170 ( Time.ZonedTime
3171 (Time.LocalTime
3172 (Time.fromGregorian 2000 01 01)
3173 (Time.TimeOfDay 0 0 0))
3174 (Time.utc)
3175 , [] )
3176 , Transaction.description="some description"
3177 , Transaction.postings = Posting.from_List
3178 [ (Posting.nil ("A":|["B", "C"]))
3179 { Posting.amounts = Data.Map.fromList
3180 [ ("$", Amount.nil
3181 { Amount.quantity = 1
3182 , Amount.style = Amount.Style.nil
3183 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3184 , Amount.Style.unit_spaced = Just False
3185 }
3186 , Amount.unit = "$"
3187 })
3188 ]
3189 }
3190 , (Posting.nil ("a":|["b", "c"]))
3191 { Posting.comments = ["first comment","second comment","third comment"]
3192 }
3193 ]
3194 })
3195 ~?=
3196 "2000/01/01 some description\n\ta:b:c\n\t\t; first comment\n\t\t; second comment\n\t\t; third comment\n\tA:B:C $1")
3197 , "2000/01/01 some description\\n\\tA:B:C $1\\n\\tAA:BB:CC $123" ~:
3198 ((Format.Ledger.Write.show False $
3199 Format.Ledger.Write.transaction $
3200 Transaction.nil
3201 { Transaction.dates=
3202 ( Time.ZonedTime
3203 (Time.LocalTime
3204 (Time.fromGregorian 2000 01 01)
3205 (Time.TimeOfDay 0 0 0))
3206 (Time.utc)
3207 , [] )
3208 , Transaction.description="some description"
3209 , Transaction.postings = Posting.from_List
3210 [ (Posting.nil ("A":|["B", "C"]))
3211 { Posting.amounts = Data.Map.fromList
3212 [ ("$", Amount.nil
3213 { Amount.quantity = 1
3214 , Amount.style = Amount.Style.nil
3215 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3216 , Amount.Style.unit_spaced = Just False
3217 }
3218 , Amount.unit = "$"
3219 })
3220 ]
3221 }
3222 , (Posting.nil ("AA":|["BB", "CC"]))
3223 { Posting.amounts = Data.Map.fromList
3224 [ ("$", Amount.nil
3225 { Amount.quantity = 123
3226 , Amount.style = Amount.Style.nil
3227 { Amount.Style.unit_side = Just Amount.Style.Side_Left
3228 , Amount.Style.unit_spaced = Just False
3229 }
3230 , Amount.unit = "$"
3231 })
3232 ]
3233 }
3234 ]
3235 })
3236 ~?=
3237 "2000/01/01 some description\n\tA:B:C $1\n\tAA:BB:CC $123")
3238 ]
3239 ]
3240 ]
3241 ]
3242 ]