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