Skip to content

Commit 41523b5

Browse files
committed
Switched every float64s to big.Rat
1 parent 0cc7fe3 commit 41523b5

File tree

4 files changed

+84
-94
lines changed

4 files changed

+84
-94
lines changed

pkg/pricing/basket_test.go

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,15 @@ func TestBasket_Add(t *testing.T) {
2222
So(basket, ShouldNotBeNil)
2323
So(basket.Length(), ShouldEqual, 0)
2424

25-
err := basket.Add(NewUsageByPathWithQuantity("/compute/c1/run", 1))
25+
err := basket.Add(NewUsageByPathWithQuantity("/compute/c1/run", big.NewRat(1, 1)))
2626
So(err, ShouldBeNil)
2727
So(basket.Length(), ShouldEqual, 1)
2828

29-
err = basket.Add(NewUsageByPathWithQuantity("/compute/c1/run", 42))
29+
err = basket.Add(NewUsageByPathWithQuantity("/compute/c1/run", big.NewRat(42, 1)))
3030
So(err, ShouldBeNil)
3131
So(basket.Length(), ShouldEqual, 2)
3232

33-
err = basket.Add(NewUsageByPathWithQuantity("/compute/c1/run", 600))
33+
err = basket.Add(NewUsageByPathWithQuantity("/compute/c1/run", big.NewRat(600, 1)))
3434
So(err, ShouldBeNil)
3535
So(basket.Length(), ShouldEqual, 3)
3636
})
@@ -41,28 +41,19 @@ func TestBasket_Total(t *testing.T) {
4141
Convey("3 compute instances", func() {
4242
basket := NewBasket()
4343
So(basket, ShouldNotBeNil)
44-
current := ratZero
45-
difference := ratZero
46-
So(basket.Total(), ShouldEqualBigRat, current)
44+
So(basket.Total(), ShouldEqualBigRat, ratZero)
4745

48-
err := basket.Add(NewUsageByPathWithQuantity("/compute/c1/run", 1))
46+
err := basket.Add(NewUsageByPathWithQuantity("/compute/c1/run", big.NewRat(1, 1)))
4947
So(err, ShouldBeNil)
50-
difference = new(big.Rat).Mul(big.NewRat(60, 1), new(big.Rat).SetFloat64(0.012))
51-
current = new(big.Rat).Add(current, difference)
52-
So(basket.Total(), ShouldEqualBigRat, current)
48+
So(basket.Total(), ShouldEqualBigRat, big.NewRat(72, 100)) // 0.72
5349

54-
err = basket.Add(NewUsageByPathWithQuantity("/compute/c1/run", 42))
50+
err = basket.Add(NewUsageByPathWithQuantity("/compute/c1/run", big.NewRat(42, 1)))
5551
So(err, ShouldBeNil)
56-
difference = new(big.Rat).Mul(big.NewRat(60, 1), new(big.Rat).SetFloat64(0.012))
57-
//difference = big.NewRat(72, 100)
58-
current = new(big.Rat).Add(current, difference)
59-
So(basket.Total(), ShouldEqualBigRat, current)
52+
So(basket.Total(), ShouldEqualBigRat, big.NewRat(144, 100)) // 1.44
6053

61-
err = basket.Add(NewUsageByPathWithQuantity("/compute/c1/run", 600))
54+
err = basket.Add(NewUsageByPathWithQuantity("/compute/c1/run", big.NewRat(600, 1)))
6255
So(err, ShouldBeNil)
63-
difference = big.NewRat(6, 1)
64-
current = new(big.Rat).Add(current, difference)
65-
So(basket.Total(), ShouldEqualBigRat, current)
56+
So(basket.Total(), ShouldEqualBigRat, big.NewRat(744, 100)) // 7.44
6657
})
6758
Convey("1 compute instance with 2 volumes and 1 ip", func() {
6859
basket := NewBasket()
@@ -74,19 +65,19 @@ func TestBasket_Total(t *testing.T) {
7465
So(basket.Length(), ShouldEqual, 4)
7566

7667
basket.SetDuration(1 * time.Minute)
77-
So(basket.Total(), ShouldEqualBigRat, new(big.Rat).SetFloat64(1.36))
68+
So(basket.Total(), ShouldEqualBigRat, big.NewRat(136, 100)) // 1.36
7869

7970
basket.SetDuration(1 * time.Hour)
80-
So(basket.Total(), ShouldEqualBigRat, new(big.Rat).SetFloat64(1.36))
71+
So(basket.Total(), ShouldEqualBigRat, big.NewRat(136, 100)) // 1.36
8172

8273
basket.SetDuration(2 * time.Hour)
83-
So(basket.Total(), ShouldEqualBigRat, new(big.Rat).SetFloat64(2.32))
74+
So(basket.Total(), ShouldEqualBigRat, big.NewRat(232, 100)) // 2.32
8475

8576
basket.SetDuration(2 * 24 * time.Hour)
86-
So(basket.Total(), ShouldEqualBigRat, new(big.Rat).SetFloat64(8.39))
77+
So(basket.Total(), ShouldEqualBigRat, big.NewRat(8399, 1000)) // 8.399
8778

8879
basket.SetDuration(30 * 24 * time.Hour)
89-
So(basket.Total(), ShouldEqualBigRat, new(big.Rat).SetFloat64(1.99))
80+
So(basket.Total(), ShouldEqualBigRat, big.NewRat(11999, 1000)) // 11.999
9081
})
9182
})
9283
}

pkg/pricing/pricing.go

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
package pricing
22

3-
import "time"
3+
import (
4+
"math/big"
5+
"time"
6+
)
47

58
type PricingObject struct {
69
Path string
710
Identifier string
811
Currency string
9-
UnitPrice float64
10-
UnitQuantity float64
11-
UnitPriceCap float64
1212
UsageUnit string
13+
UnitPrice *big.Rat
14+
UnitQuantity *big.Rat
15+
UnitPriceCap *big.Rat
1316
UsageGranularity time.Duration
1417
}
1518

@@ -26,36 +29,36 @@ func init() {
2629
Path: "/compute/c1/run",
2730
Identifier: "aaaaaaaa-aaaa-4aaa-8aaa-111111111111",
2831
Currency: "EUR",
29-
UnitPrice: 0.012,
30-
UnitQuantity: 60,
31-
UnitPriceCap: 6,
32+
UnitPrice: big.NewRat(12, 1000), // 0.012
33+
UnitQuantity: big.NewRat(60000, 1000), // 60
34+
UnitPriceCap: big.NewRat(6000, 1000), // 6
3235
UsageGranularity: time.Minute,
3336
},
3437
{
3538
Path: "/ip/dynamic",
3639
Identifier: "467116bf-4631-49fb-905b-e07701c2db11",
3740
Currency: "EUR",
38-
UnitPrice: 0.004,
39-
UnitQuantity: 60,
40-
UnitPriceCap: 1.99,
41+
UnitPrice: big.NewRat(4, 1000), // 0.004
42+
UnitQuantity: big.NewRat(60000, 1000), // 60
43+
UnitPriceCap: big.NewRat(1999, 1000), // 1.99
4144
UsageGranularity: time.Minute,
4245
},
4346
{
4447
Path: "/ip/reserved",
4548
Identifier: "467116bf-4631-49fb-905b-e07701c2db22",
4649
Currency: "EUR",
47-
UnitPrice: 0.004,
48-
UnitQuantity: 60,
49-
UnitPriceCap: 1.99,
50+
UnitPrice: big.NewRat(4, 1000), // 0.004
51+
UnitQuantity: big.NewRat(60000, 1000), // 60
52+
UnitPriceCap: big.NewRat(1990, 1000), // 1.99
5053
UsageGranularity: time.Minute,
5154
},
5255
{
5356
Path: "/storage/local/ssd/storage",
5457
Identifier: "bbbbbbbb-bbbb-4bbb-8bbb-111111111113",
5558
Currency: "EUR",
56-
UnitPrice: 0.004,
57-
UnitQuantity: 50,
58-
UnitPriceCap: 2,
59+
UnitPrice: big.NewRat(4, 1000), // 0.004
60+
UnitQuantity: big.NewRat(50000, 1000), // 50
61+
UnitPriceCap: big.NewRat(2000, 1000), // 2
5962
UsageGranularity: time.Hour,
6063
},
6164
}

pkg/pricing/usage.go

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,22 +11,22 @@ type Usage struct {
1111
}
1212

1313
func NewUsageByPath(objectPath string) Usage {
14-
return NewUsageByPathWithQuantity(objectPath, 0)
14+
return NewUsageByPathWithQuantity(objectPath, ratZero)
1515
}
1616

17-
func NewUsageByPathWithQuantity(objectPath string, quantity float64) Usage {
17+
func NewUsageByPathWithQuantity(objectPath string, quantity *big.Rat) Usage {
1818
return NewUsageWithQuantity(CurrentPricing.GetByPath(objectPath), quantity)
1919
}
2020

21-
func NewUsageWithQuantity(object *PricingObject, quantity float64) Usage {
21+
func NewUsageWithQuantity(object *PricingObject, quantity *big.Rat) Usage {
2222
return Usage{
2323
PricingObject: object,
24-
Quantity: new(big.Rat).SetFloat64(quantity),
24+
Quantity: quantity,
2525
}
2626
}
2727

2828
func NewUsage(object *PricingObject) Usage {
29-
return NewUsageWithQuantity(object, 0)
29+
return NewUsageWithQuantity(object, ratZero)
3030
}
3131

3232
func (u *Usage) SetQuantity(quantity *big.Rat) error {
@@ -55,15 +55,14 @@ func (u *Usage) SetStartEnd(start, end time.Time) error {
5555
}
5656

5757
func (u *Usage) BillableQuantity() *big.Rat {
58-
if u.Quantity.Cmp(big.NewRat(0, 1)) < 1 {
58+
if u.Quantity.Cmp(ratZero) < 1 {
5959
return big.NewRat(0, 1)
6060
}
6161

6262
//return math.Ceil(u.Quantity/u.PricingObject.UnitQuantity) * u.PricingObject.UnitQuantity
63-
unitQuantity := new(big.Rat).SetFloat64(u.PricingObject.UnitQuantity)
64-
quantityQuotient := new(big.Rat).Quo(u.Quantity, unitQuantity)
63+
quantityQuotient := new(big.Rat).Quo(u.Quantity, u.PricingObject.UnitQuantity)
6564
ceil := new(big.Rat).SetInt(ratCeil(quantityQuotient))
66-
return new(big.Rat).Mul(ceil, unitQuantity)
65+
return new(big.Rat).Mul(ceil, u.PricingObject.UnitQuantity)
6766
}
6867

6968
func (u *Usage) LostQuantity() *big.Rat {
@@ -75,9 +74,6 @@ func (u *Usage) LostQuantity() *big.Rat {
7574
func (u *Usage) Total() *big.Rat {
7675
//return math.Min(u.PricingObject.UnitPrice * u.BillableQuantity(), u.PricingObject.UnitPriceCap)
7776

78-
unitPrice := new(big.Rat).SetFloat64(u.PricingObject.UnitPrice)
79-
total := new(big.Rat).Mul(u.BillableQuantity(), unitPrice)
80-
81-
unitPriceCap := new(big.Rat).SetFloat64(u.PricingObject.UnitPriceCap)
82-
return ratMin(total, unitPriceCap)
77+
total := new(big.Rat).Mul(u.BillableQuantity(), u.PricingObject.UnitPrice)
78+
return ratMin(total, u.PricingObject.UnitPriceCap)
8379
}

pkg/pricing/usage_test.go

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010

1111
func TestNewUsageByPathWithQuantity(t *testing.T) {
1212
Convey("Testing NewUsageByPathWithQuantity()", t, func() {
13-
usage := NewUsageByPathWithQuantity("/compute/c1/run", 1)
13+
usage := NewUsageByPathWithQuantity("/compute/c1/run", big.NewRat(1, 1))
1414
So(usage.PricingObject.Path, ShouldEqual, "/compute/c1/run")
1515
So(usage.Quantity, ShouldEqualBigRat, big.NewRat(1, 1))
1616
})
@@ -27,7 +27,7 @@ func TestNewUsageByPath(t *testing.T) {
2727
func TestNewUsageWithQuantity(t *testing.T) {
2828
Convey("Testing NewUsageWithQuantity()", t, func() {
2929
object := CurrentPricing.GetByPath("/compute/c1/run")
30-
usage := NewUsageWithQuantity(object, 1)
30+
usage := NewUsageWithQuantity(object, big.NewRat(1, 1))
3131
So(usage.PricingObject.Path, ShouldEqual, "/compute/c1/run")
3232
So(usage.Quantity, ShouldEqualBigRat, big.NewRat(1, 1))
3333
})
@@ -154,110 +154,110 @@ func TestUsage_SetDuration(t *testing.T) {
154154
func TestUsage_BillableQuantity(t *testing.T) {
155155
Convey("Testing Usage.BillableQuantity()", t, FailureContinues, func() {
156156
object := &PricingObject{
157-
UnitQuantity: 60,
157+
UnitQuantity: big.NewRat(60, 1),
158158
}
159-
usage := NewUsageWithQuantity(object, -1)
159+
usage := NewUsageWithQuantity(object, big.NewRat(-1, 1))
160160
So(usage.BillableQuantity(), ShouldEqualBigRat, big.NewRat(0, 1))
161161

162-
usage = NewUsageWithQuantity(object, -1000)
162+
usage = NewUsageWithQuantity(object, big.NewRat(-1000, 1))
163163
So(usage.BillableQuantity(), ShouldEqualBigRat, big.NewRat(0, 1))
164164

165-
usage = NewUsageWithQuantity(object, 0)
165+
usage = NewUsageWithQuantity(object, big.NewRat(0, 1))
166166
So(usage.BillableQuantity(), ShouldEqualBigRat, big.NewRat(0, 1))
167167

168-
usage = NewUsageWithQuantity(object, 1)
168+
usage = NewUsageWithQuantity(object, big.NewRat(1, 1))
169169
So(usage.BillableQuantity(), ShouldEqualBigRat, big.NewRat(60, 1))
170170

171-
usage = NewUsageWithQuantity(object, 59)
171+
usage = NewUsageWithQuantity(object, big.NewRat(59, 1))
172172
So(usage.BillableQuantity(), ShouldEqualBigRat, big.NewRat(60, 1))
173173

174-
usage = NewUsageWithQuantity(object, 59.9999)
174+
usage = NewUsageWithQuantity(object, big.NewRat(599999, 10000)) // 59.9999
175175
So(usage.BillableQuantity(), ShouldEqualBigRat, big.NewRat(60, 1))
176176

177-
usage = NewUsageWithQuantity(object, 60)
177+
usage = NewUsageWithQuantity(object, big.NewRat(60, 1))
178178
So(usage.BillableQuantity(), ShouldEqualBigRat, big.NewRat(60, 1))
179179

180-
usage = NewUsageWithQuantity(object, 60.00001)
180+
usage = NewUsageWithQuantity(object, big.NewRat(6000001, 100000)) // 60.00001
181181
So(usage.BillableQuantity(), ShouldEqualBigRat, big.NewRat(60*2, 1))
182182

183-
usage = NewUsageWithQuantity(object, 61)
183+
usage = NewUsageWithQuantity(object, big.NewRat(61, 1))
184184
So(usage.BillableQuantity(), ShouldEqualBigRat, big.NewRat(60*2, 1))
185185

186-
usage = NewUsageWithQuantity(object, 119)
186+
usage = NewUsageWithQuantity(object, big.NewRat(119, 1))
187187
So(usage.BillableQuantity(), ShouldEqualBigRat, big.NewRat(60*2, 1))
188188

189-
usage = NewUsageWithQuantity(object, 121)
189+
usage = NewUsageWithQuantity(object, big.NewRat(121, 1))
190190
So(usage.BillableQuantity(), ShouldEqualBigRat, big.NewRat(60*3, 1))
191191

192-
usage = NewUsageWithQuantity(object, 1000)
192+
usage = NewUsageWithQuantity(object, big.NewRat(1000, 1))
193193
So(usage.BillableQuantity(), ShouldEqualBigRat, big.NewRat(60*17, 1))
194194
})
195195
}
196196

197197
func TestUsage_LostQuantity(t *testing.T) {
198198
Convey("Testing Usage.LostQuantity()", t, FailureContinues, func() {
199199
object := &PricingObject{
200-
UnitQuantity: 60,
200+
UnitQuantity: big.NewRat(60, 1),
201201
}
202-
usage := NewUsageWithQuantity(object, -1)
202+
usage := NewUsageWithQuantity(object, big.NewRat(-1, 1))
203203
So(usage.LostQuantity(), ShouldEqualBigRat, big.NewRat(0, 1))
204204

205-
usage = NewUsageWithQuantity(object, -1000)
205+
usage = NewUsageWithQuantity(object, big.NewRat(-1000, 1))
206206
So(usage.LostQuantity(), ShouldEqualBigRat, big.NewRat(0, 1))
207207

208-
usage = NewUsageWithQuantity(object, 0)
208+
usage = NewUsageWithQuantity(object, big.NewRat(0, 1))
209209
So(usage.LostQuantity(), ShouldEqualBigRat, big.NewRat(0, 1))
210210

211-
usage = NewUsageWithQuantity(object, 1)
211+
usage = NewUsageWithQuantity(object, big.NewRat(1, 1))
212212
So(usage.LostQuantity(), ShouldEqualBigRat, big.NewRat(60-1, 1))
213213

214-
usage = NewUsageWithQuantity(object, 59)
214+
usage = NewUsageWithQuantity(object, big.NewRat(59, 1))
215215
So(usage.LostQuantity(), ShouldEqualBigRat, big.NewRat(60-59, 1))
216216

217-
usage = NewUsageWithQuantity(object, 59.9999)
218-
So(usage.LostQuantity(), ShouldEqualBigRat, new(big.Rat).Sub(big.NewRat(60, 1), new(big.Rat).SetFloat64(59.9999)))
217+
usage = NewUsageWithQuantity(object, big.NewRat(599999, 10000)) // 59.9999
218+
So(usage.LostQuantity(), ShouldEqualBigRat, new(big.Rat).Sub(big.NewRat(60, 1), big.NewRat(599999, 10000)))
219219

220-
usage = NewUsageWithQuantity(object, 60)
220+
usage = NewUsageWithQuantity(object, big.NewRat(60, 1))
221221
So(usage.LostQuantity(), ShouldEqualBigRat, big.NewRat(0, 1))
222222

223-
usage = NewUsageWithQuantity(object, 60.00001)
224-
So(usage.LostQuantity(), ShouldEqualBigRat, new(big.Rat).SetFloat64(60*2-60.00001))
223+
usage = NewUsageWithQuantity(object, big.NewRat(6000001, 100000)) // 60.00001
224+
So(usage.LostQuantity(), ShouldEqualBigRat, big.NewRat(6000000*2-6000001, 100000))
225225

226-
usage = NewUsageWithQuantity(object, 61)
226+
usage = NewUsageWithQuantity(object, big.NewRat(61, 1))
227227
So(usage.LostQuantity(), ShouldEqualBigRat, big.NewRat(60*2-61, 1))
228228

229-
usage = NewUsageWithQuantity(object, 119)
229+
usage = NewUsageWithQuantity(object, big.NewRat(119, 1))
230230
So(usage.LostQuantity(), ShouldEqualBigRat, big.NewRat(60*2-119, 1))
231231

232-
usage = NewUsageWithQuantity(object, 121)
232+
usage = NewUsageWithQuantity(object, big.NewRat(121, 1))
233233
So(usage.LostQuantity(), ShouldEqualBigRat, big.NewRat(60*3-121, 1))
234234

235-
usage = NewUsageWithQuantity(object, 1000)
235+
usage = NewUsageWithQuantity(object, big.NewRat(1000, 1))
236236
So(usage.LostQuantity(), ShouldEqualBigRat, big.NewRat(60*17-1000, 1))
237237
})
238238
}
239239

240240
func TestUsage_Total(t *testing.T) {
241241
Convey("Testing Usage.Total()", t, FailureContinues, func() {
242242
object := PricingObject{
243-
UnitQuantity: 60,
244-
UnitPrice: 0.012,
245-
UnitPriceCap: 6,
243+
UnitQuantity: big.NewRat(60, 1),
244+
UnitPrice: big.NewRat(12, 1000), // 0.012
245+
UnitPriceCap: big.NewRat(6, 1),
246246
}
247247

248-
usage := NewUsageWithQuantity(&object, -1)
248+
usage := NewUsageWithQuantity(&object, big.NewRat(-1, 1))
249249
So(usage.Total(), ShouldEqualBigRat, big.NewRat(0, 1))
250250

251-
usage = NewUsageWithQuantity(&object, 0)
251+
usage = NewUsageWithQuantity(&object, big.NewRat(0, 1))
252252
So(usage.Total(), ShouldEqualBigRat, big.NewRat(0, 1))
253253

254-
usage = NewUsageWithQuantity(&object, 1)
255-
So(usage.Total(), ShouldEqualBigRat, new(big.Rat).Mul(big.NewRat(60, 1), new(big.Rat).SetFloat64(0.012)))
254+
usage = NewUsageWithQuantity(&object, big.NewRat(1, 1))
255+
So(usage.Total(), ShouldEqualBigRat, big.NewRat(60*12, 1000)) // 60 * 0.012
256256

257-
usage = NewUsageWithQuantity(&object, 61)
258-
So(usage.Total(), ShouldEqualBigRat, new(big.Rat).Mul(big.NewRat(120, 1), new(big.Rat).SetFloat64(0.012)))
257+
usage = NewUsageWithQuantity(&object, big.NewRat(61, 1))
258+
So(usage.Total(), ShouldEqualBigRat, big.NewRat(120*12, 1000)) // 120 * 0.012
259259

260-
usage = NewUsageWithQuantity(&object, 1000)
260+
usage = NewUsageWithQuantity(&object, big.NewRat(1000, 1))
261261
So(usage.Total(), ShouldEqualBigRat, big.NewRat(6, 1))
262262
})
263263
}

0 commit comments

Comments
 (0)