Files
Alessandro ScandoneandGitHub a804f6edf1 feat: color as first class citizen (#160)
reworked balances representation (both internal and external) so that it handles colors as an ad-hoc field instead of relying of string convetions
2026-06-15 15:13:22 +02:00

291 lines
5.4 KiB
Go

package interpreter
import (
"math/big"
"testing"
"github.com/stretchr/testify/require"
)
func TestGetAssetsExcludesColoredBalances(t *testing.T) {
// Scaling converts only uncolored balances and emits uncolored postings, so a
// colored balance for the same base asset must not be offered as a candidate.
assets := getAssets([]AccountBalance{
{Asset: "USD", Color: "", Amount: big.NewInt(2)},
{Asset: "USD/4", Color: "RED", Amount: big.NewInt(999)}, // colored: excluded
{Asset: "USD/2", Color: "", Amount: big.NewInt(50)},
{Asset: "EUR", Color: "", Amount: big.NewInt(7)}, // different base: excluded
}, "USD")
require.Equal(t, map[int64]*big.Int{
0: big.NewInt(2),
2: big.NewInt(50),
}, assets)
}
func TestScalingAvoidSwappingAlreadyHaveAsset(t *testing.T) {
// Need [USD/2 200]
// Got: {USD/2 100, USD 2}
// we only want [USD 1] to be swapped
sol, got := findScalingSolution(
big.NewInt(200),
2,
map[int64]*big.Int{
2: big.NewInt(100),
0: big.NewInt(2),
})
require.Equal(t, []scalePair{
{0, big.NewInt(1)},
}, sol)
require.Equal(t, big.NewInt(100), got)
}
func TestScalingAvoidSpareAmt(t *testing.T) {
// Need [USD/2 1]
// Got: {USD 99}
sol, got := findScalingSolution(
big.NewInt(1),
2,
map[int64]*big.Int{
0: big.NewInt(99),
})
require.Equal(t, []scalePair{
{0, big.NewInt(1)},
}, sol)
require.Equal(t, big.NewInt(100), got)
}
func TestScalingAvoidSpareAmt2(t *testing.T) {
// Need [USD/2 1]
// Got: {USD 99}
sol, got := findScalingSolution(
big.NewInt(399),
2,
map[int64]*big.Int{
0: big.NewInt(9999999),
})
require.Equal(t, []scalePair{
{0, big.NewInt(4)},
}, sol)
require.Equal(t, big.NewInt(400), got)
}
func TestScalingDownAvoidSpareAmt(t *testing.T) {
sol, got := findScalingSolution(
big.NewInt(1),
0,
map[int64]*big.Int{
2: big.NewInt(123),
})
require.Equal(t, []scalePair{
{2, big.NewInt(100)},
}, sol)
require.Equal(t, big.NewInt(1), got)
}
func TestScalingZeroNeeded(t *testing.T) {
sol, tot := findScalingSolution(
big.NewInt(0),
42,
map[int64]*big.Int{
2: big.NewInt(100),
1: big.NewInt(1),
})
require.Equal(t, []scalePair(nil), sol)
require.Equal(t, big.NewInt(0), tot)
}
func TestDoNotAllowSpare(t *testing.T) {
sol, tot := findScalingSolution(
// Need [EUR/2 1]
big.NewInt(1),
2,
// Have: {EUR: 99}
map[int64]*big.Int{
0: big.NewInt(99),
})
require.Equal(t, []scalePair{
{0, big.NewInt(1)},
}, sol)
require.Equal(t, big.NewInt(100), tot)
}
func TestRepro(t *testing.T) {
sol, tot := findScalingSolution(
// Need [EUR/2 400]
big.NewInt(400),
2,
// Have: {EUR: 99, EUR/2: 1}
map[int64]*big.Int{
2: big.NewInt(1),
0: big.NewInt(99),
})
require.Equal(t, []scalePair{
{0, big.NewInt(4)},
}, sol)
require.Equal(t, big.NewInt(400), tot)
}
func TestScalingSameAsset(t *testing.T) {
sol, tot := findScalingSolution(
// Need [EUR/2 200]
big.NewInt(200),
2,
// Have: {EUR/2: 201}
map[int64]*big.Int{
2: big.NewInt(201),
})
require.Equal(t, []scalePair(nil), sol)
require.Equal(t, big.NewInt(0), tot)
}
func TestScalingSolutionLowerScale(t *testing.T) {
sol, _ := findScalingSolution(
// Need [COIN 1]
big.NewInt(1),
0,
// Got: {COIN/2 900}
map[int64]*big.Int{
2: big.NewInt(900),
})
require.Equal(t, []scalePair{
{2, big.NewInt(100)},
}, sol)
}
func TestScalingSolutionHigherScale(t *testing.T) {
sol, _ := findScalingSolution(
// Need [EUR/2 200]
big.NewInt(200),
2,
// Have: {EUR: 4} (eq to EUR/2 400)
map[int64]*big.Int{
0: big.NewInt(4),
})
require.Equal(t, []scalePair{
{0, big.NewInt(2)},
}, sol)
}
func TestScalingSolutionHigherScaleNoSolution(t *testing.T) {
// TODO change name
sol, _ := findScalingSolution(
// Needed: [COIN/2 1]
big.NewInt(1),
2,
// Got: {COIN: 100, COIN/1: 100}
map[int64]*big.Int{
0: big.NewInt(100),
1: big.NewInt(100),
})
require.Equal(t, []scalePair{
{1, big.NewInt(1)},
}, sol)
}
func TestNoSolution(t *testing.T) {
sol, got := findScalingSolution(
// Need [USD/2 400]
big.NewInt(400),
2,
map[int64]*big.Int{
0: big.NewInt(1),
2: big.NewInt(1),
3: big.NewInt(1),
})
require.Equal(t, big.NewInt(100), got)
require.Equal(t, []scalePair{
{0, big.NewInt(1)},
}, sol)
}
func TestNoSolution2(t *testing.T) {
sol, tot := findScalingSolution(
// Need [USD/2 400]
big.NewInt(400),
2,
map[int64]*big.Int{
0: big.NewInt(1),
2: big.NewInt(200),
3: big.NewInt(10),
})
require.Equal(t, []scalePair{
{3, big.NewInt(10)},
{0, big.NewInt(1)},
}, sol)
require.Equal(t, big.NewInt(100+1), tot)
}
func TestUnboundedScalingSameAsset(t *testing.T) {
sol, tot := findScalingSolution(
// Need [USD/2 *]
nil,
2,
// Have: {EUR/2: 201}
map[int64]*big.Int{
2: big.NewInt(123),
})
require.Equal(t, []scalePair(nil), sol)
require.Equal(t, big.NewInt(0), tot)
}
func TestUnboundedScalingLowerAsset(t *testing.T) {
sol, _ := findScalingSolution(
nil,
2,
map[int64]*big.Int{
0: big.NewInt(1),
})
require.Equal(t, []scalePair{
{0, big.NewInt(1)},
}, sol)
}
func TestUnboundedScalinHigherAsset(t *testing.T) {
sol, _ := findScalingSolution(
nil,
2,
map[int64]*big.Int{
3: big.NewInt(10),
})
require.Equal(t,
[]scalePair{
{3, big.NewInt(10)},
},
sol)
}
func TestUnboundedScalinHigherAssetTrimRemainder(t *testing.T) {
sol, _ := findScalingSolution(
nil,
2,
map[int64]*big.Int{
3: big.NewInt(15),
})
require.Equal(t, []scalePair{
{3, big.NewInt(10)},
}, sol)
}