ana-ledger/src/ledger/file_test.go

468 lines
9.3 KiB
Go

package ledger
import (
"os"
"path"
"path/filepath"
"testing"
)
func TestFileAmend(t *testing.T) {
cases := map[string]struct {
from string
old Delta
now Delta
want string
}{
"multi recipient": {
from: `
2006-01-02 description
recipientA $3.45
recipientB $6.45
payee
`,
old: Delta{
Date: "2006-01-02",
Name: "recipientB",
Value: 6.45,
Currency: "$",
Description: "description",
},
now: Delta{
Date: "2106-11-12",
Name: "recipientC",
Value: 16.45,
Currency: "T",
Description: "1description",
},
want: `
2006-01-02 description
recipientB $-6.45
payee
2106-11-12 1description
recipientC 16.45 T
payee`,
},
"recipient": {
from: `
2006-01-02 description
recipient $3.45
payee $-3.45
`,
old: Delta{
Date: "2006-01-02",
Name: "recipient",
Value: 3.45,
Currency: "$",
Description: "description",
},
now: Delta{
Date: "2106-11-12",
Name: "1recipient",
Value: 13.45,
Currency: "T",
Description: "1description",
},
want: `
2006-01-02 description
recipient $-3.45
payee
2106-11-12 1description
1recipient 13.45 T
payee`,
},
"payee": {
from: `
2006-01-02 description
recipient $3.45
payee
`,
old: Delta{
Date: "2006-01-02",
Name: "payee",
Value: -3.45,
Currency: "$",
Description: "description",
},
now: Delta{
Date: "2106-11-12",
Name: "1payee",
Value: -13.45,
Currency: "T",
Description: "1description",
},
want: `
2006-01-02 description
payee $3.45
recipient
2106-11-12 1description
1payee -13.45 T
recipient`,
},
"was set": {
from: `
2006-01-02 description
recipient $3.45
payee
`,
old: Delta{
Date: "2006-01-02",
Name: "recipient",
Value: 3.45,
Currency: "$",
Description: "description",
},
now: Delta{
Date: "2106-11-12",
Name: "1recipient",
Value: 13.45,
Currency: "T",
Description: "1description",
},
want: `
2006-01-02 description
recipient $-3.45
payee
2106-11-12 1description
1recipient 13.45 T
payee`,
},
}
for name, d := range cases {
c := d
t.Run(name, func(t *testing.T) {
p := path.Join(t.TempDir(), "dat")
if err := os.WriteFile(p, []byte(c.from), os.ModePerm); err != nil {
t.Fatal(err)
}
files, err := NewFiles(p)
if err != nil {
t.Fatal(err)
} else if deltas, err := files.Deltas(); err != nil {
t.Fatal(err)
} else if filtered := deltas.Like(func(d Delta) bool {
c.old.Transaction = d.Transaction
c.old.Payee = d.Payee
return d.equivalent(c.old)
}); len(filtered) != 1 {
t.Fatalf("input \n\t%s \ndidnt include old \n\t%+v \nin \n\t%+v: \n\t%+v", c.from, c.old, deltas, filtered)
}
if err := files.Amend(c.old, c.now); err != nil {
t.Fatal(err)
} else if b, err := os.ReadFile(path.Join(path.Dir(p), "inbox.txt")); err != nil {
t.Fatal(err)
} else if string(b) != c.want {
t.Fatalf("expected \n\t%q\nbut got\n\t%q\n\t%s", c.want, b, b)
}
})
}
}
func TestFileAdd(t *testing.T) {
filesAppendDelim = " "
payee := "name:3"
delta := Delta{
Date: "2999-88-77",
Description: "66",
Name: "name:1",
Value: 2.00,
Currency: USD,
}
cases := map[string]struct {
given []byte
want string
}{
"no file": {
given: nil,
want: `
2999-88-77 66
name:1 $2.00
name:3`,
},
"empty file": {
given: []byte{},
want: `
2999-88-77 66
name:1 $2.00
name:3`,
},
"happy without trailing whitespace": {
given: []byte(`
2000-01-02 desc
name:1 $1.00
name:2 $-1.00`),
want: `
2000-01-02 desc
name:1 $1.00
name:2 $-1.00
2999-88-77 66
name:1 $2.00
name:3`,
},
"happy with trailing newline": {
given: []byte(`
2000-01-02 desc
name:1 $1.00
name:2 $-1.00
`),
want: `
2000-01-02 desc
name:1 $1.00
name:2 $-1.00
2999-88-77 66
name:1 $2.00
name:3`,
},
}
for name, d := range cases {
c := d
t.Run(name, func(t *testing.T) {
p := path.Join(t.TempDir(), "inbox.txt")
if c.given != nil {
if err := os.WriteFile(p, []byte(c.given), os.ModePerm); err != nil {
t.Fatal(err)
}
}
f, err := NewFiles(p)
if err != nil {
t.Fatal(err)
}
if err := f.Add(payee, delta); err != nil {
t.Fatal(err)
}
if got, err := os.ReadFile(p); err != nil {
t.Fatal(err)
} else if string(got) != c.want {
t.Errorf("wanted\n\t%s, got\n\t%s", c.want, got)
}
})
}
}
func TestFileTestdataMacroWithBPI(t *testing.T) {
paths, err := filepath.Glob("./testdata/macro.d/*")
if err != nil {
t.Fatal(err)
}
t.Log(paths)
f, err := NewFiles(paths[0], paths[1:]...)
if err != nil {
t.Fatal(err)
}
deltas, err := f.Deltas()
if err != nil {
t.Fatal(err)
}
bpis, err := NewBPIs("./testdata/bpi.bpi")
if err != nil {
t.Fatal(err)
}
t.Run("bal like", func(t *testing.T) {
bal := deltas.Like(LikeName(`^AssetAccount:Bond`)).Balances().WithBPIs(bpis)
for k, v := range bal {
t.Logf("%s: %+v", k, v)
}
})
t.Run("reg like", func(t *testing.T) {
reg := deltas.Like(LikeName(`^AssetAccount:Bond`)).Register()
for k, v := range reg {
t.Logf("%s: %+v", k, v.WithBPIs(bpis))
}
})
}
func TestFileTestdata(t *testing.T) {
t.Run("macro.d", func(t *testing.T) {
paths, err := filepath.Glob("./testdata/macro.d/*")
if err != nil {
t.Fatal(err)
}
f, err := NewFiles(paths[0], paths[1:]...)
if err != nil {
t.Fatal(err)
}
deltas, err := f.Deltas()
if err != nil {
t.Fatal(err)
}
t.Run("deltas", func(t *testing.T) {
for i := range deltas {
t.Logf("%+v", deltas[i].Debug())
}
})
t.Run("balances", func(t *testing.T) {
balances := deltas.Balances()
for k, v := range balances {
t.Logf("%s: %+v", k, v)
}
})
t.Run("balances like", func(t *testing.T) {
balances := deltas.Like(LikeName(`^AssetAccount:`)).Balances()
for k, v := range balances {
t.Logf("%s: %+v", k, v)
}
})
})
t.Run("single files", func(t *testing.T) {
paths, err := filepath.Glob("./testdata/*.dat")
if err != nil {
t.Fatal(err)
}
for _, pathd := range paths {
path := pathd
t.Run(path, func(t *testing.T) {
f, err := NewFiles(path)
if err != nil {
t.Fatal(err)
}
deltas, err := f.Deltas()
if err != nil {
t.Fatal(err)
}
t.Run("deltas", func(t *testing.T) {
for i := range deltas {
t.Logf("%+v", deltas[i].Debug())
}
})
t.Run("balances", func(t *testing.T) {
balances := deltas.Balances()
for k, v := range balances {
t.Logf("%s: %+v", k, v)
}
})
t.Run("balances like", func(t *testing.T) {
balances := deltas.Like(LikeName(`AssetAccount:Cash:Fidelity76`)).Balances()
for k, v := range balances {
t.Logf("%s: %+v", k, v)
}
})
})
}
})
}
func TestFileDeltas(t *testing.T) {
happy := []Delta{
{
Date: "2022-12-12",
Name: "AssetAccount:Cash:Fidelity76",
Value: -97.92,
Currency: USD,
Description: "Electricity / Power Bill TG2PJ-2PLP5",
Payee: true,
fileName: "",
lineNo: 0,
},
{
Date: "2022-12-12",
Name: "Withdrawal:0:SharedHome:DominionEnergy",
Value: 97.92,
Currency: USD,
Description: "Electricity / Power Bill TG2PJ-2PLP5",
fileName: "",
lineNo: 0,
},
{
Date: "2022-12-12",
Name: "AssetAccount:Cash:Fidelity76",
Value: -1.00,
Currency: USD,
Description: "Test pay chase TG32S-BT2FF",
Payee: true,
fileName: "",
lineNo: 0,
},
{
Date: "2022-12-12",
Name: "Debts:Credit:ChaseFreedomUltdVisa",
Value: 1.00,
Currency: USD,
Description: "Test pay chase TG32S-BT2FF",
fileName: "",
lineNo: 0,
},
}
cases := map[string][]Delta{
"empty": nil,
"one": happy[:2],
"happy": happy[:],
}
for name, d := range cases {
want := d
t.Run(name, func(t *testing.T) {
fileName := "./testdata/" + name + ".dat"
f, err := NewFiles(fileName)
if err != nil {
t.Fatal(err)
}
deltas, err := f.Deltas()
if err != nil {
t.Fatal(err)
}
if len(deltas) != len(want) {
t.Error(len(deltas))
}
for i := range want {
want[i].fileName = fileName
deltas[i].lineNo = 0
if i >= len(deltas) {
break
}
if deltas[i].Transaction == "" {
t.Error(deltas[i].Transaction)
}
deltas[i].Transaction = ""
if !want[i].equivalent(deltas[i]) {
t.Errorf("[%d] \n\twant=%s, \n\t got=%s", i, want[i].Debug(), deltas[i].Debug())
}
}
})
}
}
func TestFilesOfDir(t *testing.T) {
d := t.TempDir()
files := Files([]string{d, "/dev/null"})
if paths := files.paths(); len(paths) != 1 {
t.Error(paths)
}
os.WriteFile(path.Join(d, "1"), []byte{}, os.ModePerm)
os.Mkdir(path.Join(d, "d2"), os.ModePerm)
os.WriteFile(path.Join(d, "d2", "2"), []byte{}, os.ModePerm)
if paths := files.paths(); len(paths) != 3 || paths[0] != path.Join(d, "1") || paths[1] != path.Join(d, "d2", "2") {
t.Error(paths)
}
}