| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- // Package money 十进制边界用例(极端值/超长小数/符号边界)。
- //
- // 与 amount_test.go 的分工:amount_test.go 覆盖"功能正确",
- // 本文件专门覆盖"精度与量级的边界",即旧库 float(10,3) → decimal(12,2) 收敛(设计 §11-7)
- // 最容易出问题的位置:第 3 位小数的进位、9999999999.99 边界、负值方向舍入。
- package money
- import (
- stderrors "errors"
- "testing"
- )
- // TestDecimalBoundary 极端金额的解析与回写一致性。
- func TestDecimalBoundary(t *testing.T) {
- cases := []struct {
- name string
- in string
- want Amount
- }{
- // decimal(12,2) 边界的 1 分钱精度
- {"上限减一分", "9999999999.98", MaxAmount - 1},
- {"下限加一分", "-9999999999.98", MinAmount + 1},
- // 第 3 位小数:恰好 5 进位(half-up,远离零)
- {"边界进位", "0.005", 1},
- {"边界不进位", "0.0049", 0},
- {"负边界进位", "-0.005", -1},
- // 超长小数(20 位):只看第 3 位,尾部不影响
- {"超长小数舍", "0.00499999999999999999", 0},
- {"超长小数进", "0.00500000000000000001", 1},
- // 大额 + 小数进位(整数位与小数位同时参与)
- {"大额进位", "9999999999.994", 999999999999},
- {"大额溢出", "9999999999.995", 0}, // 进位后越界 → ErrOverflow(want 占位,见下)
- }
- for _, tc := range cases {
- tc := tc
- t.Run(tc.name, func(t *testing.T) {
- got, err := NewFromYuanString(tc.in)
- if tc.name == "大额溢出" {
- if !stderrors.Is(err, ErrOverflow) {
- t.Fatalf("进位越界应返回 ErrOverflow,实得 %v(值 %d)", err, got)
- }
- return
- }
- if err != nil {
- t.Fatalf("NewFromYuanString(%q) 意外失败: %v", tc.in, err)
- }
- if got != tc.want {
- t.Fatalf("NewFromYuanString(%q) = %d,期望 %d", tc.in, got, tc.want)
- }
- // 幂等性:格式化后再解析必须回到同一值(String ↔ NewFromYuanString 互逆)
- again, err := NewFromYuanString(got.String())
- if err != nil {
- t.Fatalf("回写解析失败: %v", err)
- }
- if again != got {
- t.Fatalf("格式化回写漂移: %d → %q → %d", got, got.String(), again)
- }
- })
- }
- }
- // TestDecimalNegativeDirection 负数方向:减/加/比较不产生方向错误(欠费与冲正依赖此语义)。
- func TestDecimalNegativeDirection(t *testing.T) {
- neg, _ := NewFromYuanString("-0.01")
- zero := Amount(0)
- if !(neg.Cmp(zero) == -1) {
- t.Fatalf("负数应小于零")
- }
- if zero.Sub(neg) != Amount(1) {
- t.Fatalf("0 - (-0.01) 应为 0.01,实得 %s", zero.Sub(neg).String())
- }
- if got := neg.Add(neg).String(); got != "-0.02" {
- t.Fatalf("负数相加 = %s,期望 -0.02", got)
- }
- if got := neg.MulInt(0).String(); got != "0.00" {
- t.Fatalf("乘零 = %s,期望 0.00", got)
- }
- }
|