all repos

clerk @ 50bbb41fc735251033f1ce13bc2abca260d0e8ec

missing tooling for ledger/hledger

clerk/internal/decimal/decimal_test.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
decimal: add .Abs() and .Div(), 1 month ago
1
package decimal
2
3
import "testing"
4
5
func TestNewFromString(t *testing.T) {
6
	tests := []struct{ in, want string }{
7
		{"10.00", "10"},
8
		{"150.60", "150.6"},
9
		{".33", "0.33"},
10
		{"1.", "1"},
11
		{"0001.2300", "1.23"},
12
		{"0", "0"},
13
		{"0.00", "0"},
14
		{"-0.00", "0"},
15
		{"-20", "-20"},
16
		{"-.75", "-0.75"},
17
	}
18
	for _, tt := range tests {
19
		got, err := FromString(tt.in)
20
		if err != nil {
21
			t.Fatalf("NewFromString(%q) unexpected error: %v", tt.in, err)
22
		}
23
		if got.String() != tt.want {
24
			t.Fatalf("NewFromString(%q).String() = %q, want %q", tt.in, got.String(), tt.want)
25
		}
26
	}
27
}
28
29
func TestNewFromStringInvalid(t *testing.T) {
30
	tests := []string{
31
		"", ".", "+", "-",
32
		"1_000.00", "1,000.00",
33
		"1..0",
34
		"a1", "1a",
35
	}
36
	for _, in := range tests {
37
		if _, err := FromString(in); err == nil {
38
			t.Fatalf("NewFromString(%q) expected error", in)
39
		}
40
	}
41
}
42
43
func TestStringFixed(t *testing.T) {
44
	tests := []struct {
45
		in           string
46
		places       int
47
		decSep       byte
48
		thousandsSep byte
49
		want         string
50
	}{
51
		{"0", 0, 0, 0, "0"},
52
		{"0", 1, 0, 0, "0.0"},
53
		{"0", 2, 0, 0, "0.00"},
54
		{"0", 3, 0, 0, "0.000"},
55
		{"-0", 2, 0, 0, "0.00"},
56
		{"10", 2, 0, 0, "10.00"},
57
		{"10", 0, 0, 0, "10"},
58
		{"1.2", 2, 0, 0, "1.20"},
59
		{"1.2", 1, 0, 0, "1.2"},
60
		{"1.2", 3, 0, 0, "1.200"},
61
		{"1.234", 2, 0, 0, "1.23"},
62
		{"1.235", 2, 0, 0, "1.23"},
63
		{"-1.2", 2, 0, 0, "-1.20"},
64
		{"-1.234", 2, 0, 0, "-1.23"},
65
		{"0.001", 2, 0, 0, "0.00"},
66
		{"0.001", 4, 0, 0, "0.0010"},
67
		{"123.456789", 3, 0, 0, "123.456"},
68
		{"-123.456789", 3, 0, 0, "-123.456"},
69
		{"1.23", 2, ',', 0, "1,23"},
70
		{"0", 2, ',', 0, "0,00"},
71
		{"-1.5", 2, ',', 0, "-1,50"},
72
		{"1234.56", 2, 0, ',', "1,234.56"},
73
		{"1234567.89", 2, 0, ',', "1,234,567.89"},
74
		{"123.45", 2, 0, ',', "123.45"},
75
		{"-1234.56", 2, 0, ',', "-1,234.56"},
76
		{"1234567.89", 2, ',', '.', "1.234.567,89"},
77
		{"-1234567.89", 2, ',', '.', "-1.234.567,89"},
78
		{"0", 2, ',', '.', "0,00"},
79
	}
80
	for _, tt := range tests {
81
		d, err := FromString(tt.in)
82
		if err != nil {
83
			t.Fatalf("FromString(%q) unexpected error: %v", tt.in, err)
84
		}
85
		if got := d.StringFixed(tt.places, tt.decSep, tt.thousandsSep); got != tt.want {
86
			t.Fatalf("FromString(%q).StringFixed(%d, %q, %q) = %q, want %q",
87
				tt.in, tt.places, tt.decSep, tt.thousandsSep, got, tt.want)
88
		}
89
	}
90
}
91
92
func TestArithmetic(t *testing.T) {
93
	a, _ := FromString("1.20")
94
	b, _ := FromString(".30")
95
96
	if got := a.Add(b).String(); got != "1.5" {
97
		t.Fatalf("a+b = %q, want %q", got, "1.5")
98
	}
99
	if got := a.Sub(b).String(); got != "0.9" {
100
		t.Fatalf("a-b = %q, want %q", got, "0.9")
101
	}
102
	if got := a.Mul(b).String(); got != "0.36" {
103
		t.Fatalf("a*b = %q, want %q", got, "0.36")
104
	}
105
}
106
107
func TestAbs(t *testing.T) {
108
	tests := []struct {
109
		in, want string
110
	}{
111
		{"0", "0"},
112
		{"-0", "0"},
113
		{"0.00", "0"},
114
		{"1.5", "1.5"},
115
		{"-1.5", "1.5"},
116
		{"100", "100"},
117
		{"-100", "100"},
118
		{"0.001", "0.001"},
119
		{"-0.001", "0.001"},
120
		{"123.456", "123.456"},
121
		{"-123.456", "123.456"},
122
	}
123
	for _, tt := range tests {
124
		d, err := FromString(tt.in)
125
		if err != nil {
126
			t.Fatalf("FromString(%q) unexpected error: %v", tt.in, err)
127
		}
128
		if got := d.Abs().String(); got != tt.want {
129
			t.Fatalf("Abs(%q) = %q, want %q", tt.in, got, tt.want)
130
		}
131
	}
132
}
133
134
func TestDiv(t *testing.T) {
135
	tests := []struct {
136
		a, b, want string
137
	}{
138
		{"1", "2", "0.5"},
139
		{"10", "3", "3.3333333333"},
140
		{"1.50", "3.00", "0.5"},
141
		{"0.1", "0.3", "0.33333333333"},
142
		{"100", "10", "10"},
143
		{"-1", "2", "-0.5"},
144
		{"1", "-2", "-0.5"},
145
		{"-1", "-2", "0.5"},
146
		{"0", "5", "0"},
147
		{"5.50", "5", "1.1"},
148
		{"1000", "3", "333.3333333333"},
149
	}
150
	for _, tt := range tests {
151
		a, err := FromString(tt.a)
152
		if err != nil {
153
			t.Fatalf("FromString(%q) unexpected error: %v", tt.a, err)
154
		}
155
		b, err := FromString(tt.b)
156
		if err != nil {
157
			t.Fatalf("FromString(%q) unexpected error: %v", tt.b, err)
158
		}
159
		got := a.Div(b).String()
160
		if got != tt.want {
161
			t.Fatalf("Div(%q, %q) = %q, want %q", tt.a, tt.b, got, tt.want)
162
		}
163
	}
164
}
165
166
func TestDivByZero(t *testing.T) {
167
	defer func() {
168
		if r := recover(); r == nil {
169
			t.Fatal("expected panic on division by zero")
170
		}
171
	}()
172
	d, _ := FromString("1")
173
	d.Div(Decimal{})
174
}
175
176
func TestCmpAndNeg(t *testing.T) {
177
	a, _ := FromString("1.0")
178
	b, _ := FromString("1")
179
	c, _ := FromString("1.01")
180
181
	if a.Cmp(b) != 0 {
182
		t.Fatalf("expected %q and %q to be equal", a.String(), b.String())
183
	}
184
	if b.Cmp(c) >= 0 {
185
		t.Fatalf("expected %q to be less than %q", b.String(), c.String())
186
	}
187
	if got := b.Neg().String(); got != "-1" {
188
		t.Fatalf("Neg(1) = %q, want %q", got, "-1")
189
	}
190
	if got := (Decimal{}).Neg().String(); got != "0" {
191
		t.Fatalf("Neg(0) = %q, want %q", got, "0")
192
	}
193
}