all repos

clerk @ 8e80bf966dac8f581e04ce06b823f0ec9dfdaa96

missing tooling for ledger/hledger

clerk/journal/journal_test.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
parser: add more spec compliance..., 14 days ago
1
package journal_test
2
3
import (
4
	"path/filepath"
5
	"testing"
6
7
	"olexsmir.xyz/clerk/journal"
8
)
9
10
type test struct {
11
	desc string
12
	err  bool // file has intentional syntax errors, parser should report them
13
}
14
15
var tests = map[string]test{
16
	"actual-1ktxns-100accts.journal":            {desc: "hledger: stress test: 1000 transactions, 100 accounts, number-only account names"},
17
	"actual-accounttypes.journal":               {desc: "hledger: account type annotations (type:A, type:L) via comments"}, // todo: tags are not supported yet
18
	"actual-alias.journal":                      {desc: "hledger: account alias directives for renaming"},
19
	"actual-borrowing.journal":                  {desc: "hledger: borrowing/lending example with liabilities"},
20
	"actual-business.journal":                   {desc: "hledger: simple business transactions with commodities"},
21
	"actual-goal-budget.journal":                {desc: "hledger: goal budget using periodic transactions"},
22
	"actual-i18n-en.journal":                    {desc: "hledger: internationalization with account types in English"},
23
	"actual-ledger-baseline-opt-lots-basis.dat": {desc: "ledger: G/S prefixes"},
24
	"actual-ledger-input-divzero.dat":           {desc: "ledger: fuzz corpus, designed to cause divide-by-zero"},
25
	"actual-ledger-input-parsing.dat":           {desc: "ledger: fuzz corpus, tests EOF without newline"},
26
	"actual-ledger-input-sample.dat":            {desc: "ledger: fuzz corpus, default commodity directive"},
27
	"actual-ledger-input-standard.dat":          {desc: "ledger: fuzz corpus, standard ledger format"},
28
	"actual-ledger-input-transfer.dat":          {desc: "ledger: fuzz corpus, byte quantity (non-monetary)"},
29
	"actual-ledger-input-wow.dat":               {desc: "ledger-cli: fuzz corpus, World of Warcraft currency (1G=100s)"},
30
	"actual-multicurrency.journal":              {desc: "hledger: multi-currency transactions with HRK/EUR"},
31
	"actual-personal.journal":                   {desc: "hledger: simple personal finance example"},
32
	"actual-quickstart.journal":                 {desc: "hledger: quickstart guide with commodity directive"},
33
	"actual-sample.journal":                     {desc: "hledger: comprehensive sample with account tree"},
34
	"actual-sample2.journal":                    {desc: "hledger: sample2 with balance assertions and account directives"},
35
	"actual-status.journal":                     {desc: "hledger: tests all transaction statuses (unmarked, pending, cleared)"},
36
	"actual-templates.journal":                  {desc: "hledger: entry template examples with comments"},
37
	"actual-unicode.journal":                    {desc: "hledger: unicode in descriptions, account names, currency"},
38
	"actual-vat.journal":                        {desc: "hledger: VAT tracking example"},
39
	"apply-tag-block.dat":                       {desc: "ledger: apply-tag block directive"},
40
	"automated-posting-rule.dat":                {desc: "ledger: automated posting rules (= /^Expenses/)"},
41
	"basic-ledger.dat":                          {desc: "ledger: basic income/expense transaction"},
42
	"basic.journal":                             {desc: "hledger: minimal setup with account/commodity directives"},
43
	"broken-double-at.journal":                  {err: true, desc: "synthetic: intentionally broken (@@) syntax"},
44
	"broken-rparen.journal":                     {err: true, desc: "synthetic: intentionally broken unmatched )"},
45
	"broken-unknown-directive.journal":          {err: true, desc: "synthetic: intentionally broken unknown directive (??)"},
46
	"code-note.dat":                             {desc: "ledger: transaction with code, payee, comments"},
47
	"commodity-space.dat":                       {desc: "ledger: commodity with space before amount ($ 10.00)"},
48
	"cost-balance-assertion.dat":                {desc: "ledger: cost notation and balance assertion (@ 1 USD = 20.00 UAH)"},
49
	"directives-supported.journal":              {desc: "mixed: tests account, commodity, include, alias directives"},
50
	"ext-hledger-i18n-no.journal":               {desc: "hledger i18n example: uppercase directive values currently mis-tokenized"},
51
	"ext-hledger-self-tracking-d.dat":           {desc: "hledger self-tracking example with date+time transaction headers"},
52
	"ext-hledger-status.journal":                {desc: "hledger status example: ! (virtual:posting)"},
53
	"ext-ledger-parsing.dat":                    {desc: "ledger parsing corpus: -$ amount form"},
54
	"header-comments.journal":                   {desc: "hledger: transaction with header comment"},
55
	"inclusive-balance-star.journal":            {desc: "hledger: inclusive balance with ==*"},
56
	"multicurrency-supported.journal":           {desc: "hledger: working multi-currency with EUR exchange"},
57
	"periodic-basic.journal":                    {desc: "hledger: periodic transaction (~ monthly)"},
58
	"secondary-date-note.journal":               {desc: "hledger: secondary date and transaction note"},
59
	"status-basic.journal":                      {desc: "hledger: transaction status (pending with !)"},
60
	"unicode-cjk-emoji.journal":                 {desc: "synthetic: unicode CJK and emoji in transaction descriptions"},
61
	"unicode-cyrillic.journal":                  {desc: "synthetic: unicode Cyrillic in descriptions and account names"},
62
	"unicode-mixed-languages.journal":           {desc: "synthetic: mixed latin/cyrillic/cjk in descriptions and account names"},
63
	"virtual-posting.dat":                       {desc: "ledger: virtual/balanced postings with [brackets]"},
64
}
65
66
func TestParserOnRealJournals(t *testing.T) {
67
	for tname, tt := range tests {
68
		t.Run(tname, func(t *testing.T) {
69
			loader := journal.NewLoader()
70
			pf, err := loader.Load(filepath.Join("testdata/journals", tname))
71
			if err != nil {
72
				t.Fatalf("load err: %v", err)
73
			}
74
75
			if tt.err {
76
				if len(pf.Errors)+len(pf.FileErrors) == 0 {
77
					t.Errorf("expected parse errors but got none")
78
				}
79
				return
80
			}
81
82
			for _, e := range pf.Errors {
83
				t.Errorf("parse error: %s", e.Message)
84
			}
85
			for _, e := range pf.FileErrors {
86
				t.Errorf("file error [%s]: %s", e.Path, e.Message)
87
			}
88
		})
89
	}
90
}