[
{"name": "three quarters of a 10 GB (10,000 MB) bundle used", "args": [10000, 7500, 1, {"minor": 10, "currency": "GBP"}, null], "expect": {"used": 7500, "remaining": 2500, "overage": 0, "overageBlocks": 0, "overageCharge": {"minor": 0, "currency": "GBP"}, "capped": false, "percentUsedBasisPoints": 7500}},
{"name": "the whole bundle used exactly, nothing over", "args": [10000, 10000, 1, {"minor": 10, "currency": "GBP"}, null], "expect": {"used": 10000, "remaining": 0, "overage": 0, "overageBlocks": 0, "overageCharge": {"minor": 0, "currency": "GBP"}, "capped": false, "percentUsedBasisPoints": 10000}},
{"name": "1 MB left of 30,000 reads 99.99%, never 100%", "args": [30000, 29999, 1, {"minor": 10, "currency": "GBP"}, null], "expect": {"used": 29999, "remaining": 1, "overage": 0, "overageBlocks": 0, "overageCharge": {"minor": 0, "currency": "GBP"}, "capped": false, "percentUsedBasisPoints": 9999}},
{"name": "two thirds used rounds down to 66.66%", "args": [3, 2, 1, {"minor": 10, "currency": "GBP"}, null], "expect": {"used": 2, "remaining": 1, "overage": 0, "overageBlocks": 0, "overageCharge": {"minor": 0, "currency": "GBP"}, "capped": false, "percentUsedBasisPoints": 6666}},
{"name": "250 MB over in 100 MB blocks is three blocks", "args": [5000, 5250, 100, {"minor": 50, "currency": "GBP"}, null], "expect": {"used": 5250, "remaining": 0, "overage": 250, "overageBlocks": 3, "overageCharge": {"minor": 150, "currency": "GBP"}, "capped": false, "percentUsedBasisPoints": 10500}},
{"name": "300 MB over in 100 MB blocks is exactly three blocks", "args": [5000, 5300, 100, {"minor": 50, "currency": "GBP"}, null], "expect": {"used": 5300, "remaining": 0, "overage": 300, "overageBlocks": 3, "overageCharge": {"minor": 150, "currency": "GBP"}, "capped": false, "percentUsedBasisPoints": 10600}},
{"name": "one MB over still starts a whole block", "args": [5000, 5001, 100, {"minor": 50, "currency": "GBP"}, null], "expect": {"used": 5001, "remaining": 0, "overage": 1, "overageBlocks": 1, "overageCharge": {"minor": 50, "currency": "GBP"}, "capped": false, "percentUsedBasisPoints": 10002}},
{"name": "a runaway month is limited by the spend cap", "args": [1000, 11000, 1, {"minor": 1, "currency": "GBP"}, {"minor": 4500, "currency": "GBP"}], "expect": {"used": 11000, "remaining": 0, "overage": 10000, "overageBlocks": 10000, "overageCharge": {"minor": 4500, "currency": "GBP"}, "capped": true, "percentUsedBasisPoints": 110000}},
{"name": "under the cap, the cap does nothing", "args": [1000, 1100, 1, {"minor": 1, "currency": "GBP"}, {"minor": 4500, "currency": "GBP"}], "expect": {"used": 1100, "remaining": 0, "overage": 100, "overageBlocks": 100, "overageCharge": {"minor": 100, "currency": "GBP"}, "capped": false, "percentUsedBasisPoints": 11000}},
{"name": "a charge exactly equal to the cap is not capped", "args": [1000, 1100, 100, {"minor": 45, "currency": "GBP"}, {"minor": 45, "currency": "GBP"}], "expect": {"used": 1100, "remaining": 0, "overage": 100, "overageBlocks": 1, "overageCharge": {"minor": 45, "currency": "GBP"}, "capped": false, "percentUsedBasisPoints": 11000}},
{"name": "no allowance: pay as you go, and no percentage", "args": [0, 30, 1, {"minor": 5, "currency": "GBP"}, null], "expect": {"used": 30, "remaining": 0, "overage": 30, "overageBlocks": 30, "overageCharge": {"minor": 150, "currency": "GBP"}, "capped": false, "percentUsedBasisPoints": null}},
{"name": "nothing used against no allowance", "args": [0, 0, 1, {"minor": 5, "currency": "GBP"}, null], "expect": {"used": 0, "remaining": 0, "overage": 0, "overageBlocks": 0, "overageCharge": {"minor": 0, "currency": "GBP"}, "capped": false, "percentUsedBasisPoints": null}},
{"name": "nothing used yet", "args": [20000, 0, 1024, {"minor": 100, "currency": "GBP"}, null], "expect": {"used": 0, "remaining": 20000, "overage": 0, "overageBlocks": 0, "overageCharge": {"minor": 0, "currency": "GBP"}, "capped": false, "percentUsedBasisPoints": 0}},
{"name": "negative usage is an error", "args": [1000, -1, 1, {"minor": 10, "currency": "GBP"}, null], "expectError": "allowance and usage must be whole numbers of 0 or more"},
{"name": "a block of zero is an error", "args": [1000, 2000, 0, {"minor": 10, "currency": "GBP"}, null], "expectError": "overage block must be 1 or more"},
{"name": "a negative price is an error", "args": [1000, 2000, 1, {"minor": -10, "currency": "GBP"}, null], "expectError": "price per block must not be negative"},
{"name": "a cap in another currency is an error", "args": [1000, 2000, 1, {"minor": 10, "currency": "GBP"}, {"minor": 4500, "currency": "EUR"}], "expectError": "currency mismatch"},
{"name": "a negative cap is an error", "args": [1000, 2000, 1, {"minor": 10, "currency": "GBP"}, {"minor": -1, "currency": "GBP"}], "expectError": "overage cap must not be negative"}
]