Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/gitpod-db/go/usage_test.go
2497 views
1
// Copyright (c) 2022 Gitpod GmbH. All rights reserved.
2
// Licensed under the GNU Affero General Public License (AGPL).
3
// See License.AGPL.txt in the project root for license information.
4
5
package db_test
6
7
import (
8
"context"
9
"fmt"
10
"testing"
11
"time"
12
13
db "github.com/gitpod-io/gitpod/components/gitpod-db/go"
14
15
"github.com/gitpod-io/gitpod/components/gitpod-db/go/dbtest"
16
"github.com/google/uuid"
17
"github.com/stretchr/testify/require"
18
)
19
20
func TestFindUsageInRange(t *testing.T) {
21
conn := dbtest.ConnectForTests(t)
22
23
start := time.Date(2022, 7, 1, 0, 0, 0, 0, time.UTC)
24
end := time.Date(2022, 8, 1, 0, 0, 0, 0, time.UTC)
25
26
attributionID := db.NewTeamAttributionID(uuid.New().String())
27
28
entryBefore := dbtest.NewUsage(t, db.Usage{
29
AttributionID: attributionID,
30
EffectiveTime: db.NewVarCharTime(start.Add(-1 * 23 * time.Hour)),
31
Draft: true,
32
})
33
34
entryInside := dbtest.NewUsage(t, db.Usage{
35
AttributionID: attributionID,
36
EffectiveTime: db.NewVarCharTime(start.Add(2 * time.Minute)),
37
})
38
39
entryAfter := dbtest.NewUsage(t, db.Usage{
40
AttributionID: attributionID,
41
EffectiveTime: db.NewVarCharTime(end.Add(2 * time.Hour)),
42
})
43
44
usageEntries := []db.Usage{entryBefore, entryInside, entryAfter}
45
dbtest.CreateUsageRecords(t, conn, usageEntries...)
46
listResult, err := db.FindUsage(context.Background(), conn, &db.FindUsageParams{
47
AttributionId: attributionID,
48
From: start,
49
To: end,
50
})
51
require.NoError(t, err)
52
53
require.Equal(t, 1, len(listResult))
54
require.Equal(t, []db.Usage{entryInside}, listResult)
55
}
56
57
func TestFindUsageInRangeByUser(t *testing.T) {
58
conn := dbtest.ConnectForTests(t)
59
60
start := time.Date(2022, 7, 1, 0, 0, 0, 0, time.UTC)
61
end := time.Date(2022, 8, 1, 0, 0, 0, 0, time.UTC)
62
userID := uuid.New()
63
64
attributionID := db.NewTeamAttributionID(uuid.New().String())
65
66
entryBefore := dbtest.NewUsage(t, withUserId(userID, db.Usage{
67
AttributionID: attributionID,
68
EffectiveTime: db.NewVarCharTime(start.Add(-1 * 23 * time.Hour)),
69
Draft: true,
70
}))
71
72
entryInside := dbtest.NewUsage(t, withUserId(userID, db.Usage{
73
AttributionID: attributionID,
74
EffectiveTime: db.NewVarCharTime(start.Add(2 * time.Minute)),
75
}))
76
77
entryInsideOtherUser := dbtest.NewUsage(t, withUserId(uuid.New(), db.Usage{
78
AttributionID: attributionID,
79
EffectiveTime: db.NewVarCharTime(start.Add(2 * time.Minute)),
80
}))
81
82
entryAfter := dbtest.NewUsage(t, withUserId(userID, db.Usage{
83
AttributionID: attributionID,
84
EffectiveTime: db.NewVarCharTime(end.Add(2 * time.Hour)),
85
}))
86
87
usageEntries := []db.Usage{entryBefore, entryInside, entryInsideOtherUser, entryAfter}
88
dbtest.CreateUsageRecords(t, conn, usageEntries...)
89
listResult, err := db.FindUsage(context.Background(), conn, &db.FindUsageParams{
90
AttributionId: attributionID,
91
UserID: userID,
92
From: start,
93
To: end,
94
})
95
require.NoError(t, err)
96
97
require.Equal(t, 1, len(listResult))
98
require.Equal(t, entryInside.ID, listResult[0].ID)
99
100
summary, err := db.GetUsageSummary(context.Background(), conn, db.GetUsageSummaryParams{
101
AttributionId: attributionID,
102
UserID: userID,
103
From: start,
104
To: end,
105
})
106
require.NoError(t, err)
107
require.Equal(t, entryInside.CreditCents, summary.CreditCentsUsed)
108
109
}
110
111
func TestGetUsageSummary(t *testing.T) {
112
conn := dbtest.ConnectForTests(t)
113
114
start := time.Date(2022, 7, 1, 0, 0, 0, 0, time.UTC)
115
end := time.Date(2022, 8, 1, 0, 0, 0, 0, time.UTC)
116
117
attributionID := db.NewTeamAttributionID(uuid.New().String())
118
119
draftBefore := dbtest.NewUsage(t, db.Usage{
120
AttributionID: attributionID,
121
EffectiveTime: db.NewVarCharTime(start.Add(-1 * 23 * time.Hour)),
122
CreditCents: 100,
123
Draft: true,
124
})
125
nondraftBefore := dbtest.NewUsage(t, db.Usage{
126
AttributionID: attributionID,
127
EffectiveTime: db.NewVarCharTime(start.Add(-1 * 23 * time.Hour)),
128
CreditCents: 200,
129
Draft: false,
130
})
131
132
draftInside := dbtest.NewUsage(t, db.Usage{
133
AttributionID: attributionID,
134
EffectiveTime: db.NewVarCharTime(start.Add(2 * time.Hour)),
135
CreditCents: 300,
136
Draft: true,
137
})
138
nonDraftInside := dbtest.NewUsage(t, db.Usage{
139
AttributionID: attributionID,
140
EffectiveTime: db.NewVarCharTime(start.Add(2 * time.Hour)),
141
CreditCents: 400,
142
Draft: false,
143
})
144
145
nonDraftAfter := dbtest.NewUsage(t, db.Usage{
146
AttributionID: attributionID,
147
EffectiveTime: db.NewVarCharTime(end.Add(2 * time.Hour)),
148
CreditCents: 1000,
149
})
150
151
invoice := dbtest.NewUsage(t, db.Usage{
152
AttributionID: attributionID,
153
Kind: db.InvoiceUsageKind,
154
EffectiveTime: db.NewVarCharTime(start.Add(2 * time.Hour)),
155
CreditCents: -400,
156
Draft: false,
157
})
158
159
dbtest.CreateUsageRecords(t, conn, draftBefore, nondraftBefore, draftInside, nonDraftInside, nonDraftAfter, invoice)
160
161
tests := []struct {
162
start, end time.Time
163
excludeDrafts bool
164
// expectations
165
creditCents db.CreditCents
166
numberOfRecords int
167
}{
168
{start, end, false, 700, 2},
169
{start, end, true, 400, 1},
170
{end, end, false, 0, 0},
171
{end, end, true, 0, 0},
172
{start, start, false, 0, 0},
173
{start.Add(-500 * 24 * time.Hour), end, false, 1000, 4},
174
{start.Add(-500 * 24 * time.Hour), end.Add(500 * 24 * time.Hour), false, 2000, 5},
175
}
176
177
for i, test := range tests {
178
t.Run(fmt.Sprintf("Running test no %d", i+1), func(t *testing.T) {
179
usageSummary, err := db.GetUsageSummary(context.Background(), conn, db.GetUsageSummaryParams{
180
AttributionId: attributionID,
181
From: test.start,
182
To: test.end,
183
ExcludeDrafts: test.excludeDrafts,
184
})
185
require.NoError(t, err)
186
187
require.EqualValues(t, test.creditCents, usageSummary.CreditCentsUsed)
188
require.EqualValues(t, test.numberOfRecords, usageSummary.NumberOfRecords)
189
})
190
}
191
}
192
193
func TestInsertUsageRecords(t *testing.T) {
194
conn := dbtest.ConnectForTests(t)
195
196
attributionID := db.NewTeamAttributionID(uuid.New().String())
197
start := time.Date(2022, 7, 1, 0, 0, 0, 0, time.UTC)
198
199
usage := dbtest.NewUsage(t, db.Usage{
200
AttributionID: attributionID,
201
EffectiveTime: db.NewVarCharTime(start.Add(2 * time.Hour)),
202
Draft: true,
203
})
204
205
dbtest.CreateUsageRecords(t, conn, usage)
206
updatedDesc := "Updated Description"
207
usage.Description = updatedDesc
208
209
require.NoError(t, db.InsertUsage(context.Background(), conn, usage))
210
211
drafts, err := db.FindAllDraftUsage(context.Background(), conn)
212
require.NoError(t, err)
213
cleaned := filter(drafts, attributionID)
214
require.Equal(t, 1, len(cleaned))
215
require.NotEqual(t, updatedDesc, cleaned[0].Description)
216
}
217
218
func filter(drafts []db.Usage, attributionID db.AttributionID) []db.Usage {
219
var cleaned []db.Usage
220
for _, draft := range drafts {
221
if draft.AttributionID == attributionID {
222
cleaned = append(cleaned, draft)
223
}
224
}
225
return cleaned
226
}
227
228
func TestUpdateUsageRecords(t *testing.T) {
229
conn := dbtest.ConnectForTests(t)
230
231
attributionID := db.NewTeamAttributionID(uuid.New().String())
232
start := time.Date(2022, 7, 1, 0, 0, 0, 0, time.UTC)
233
234
usage := dbtest.NewUsage(t, db.Usage{
235
AttributionID: attributionID,
236
EffectiveTime: db.NewVarCharTime(start.Add(2 * time.Hour)),
237
Draft: true,
238
})
239
240
dbtest.CreateUsageRecords(t, conn, usage)
241
updatedDesc := "Updated Description"
242
usage.Description = updatedDesc
243
244
require.NoError(t, db.UpdateUsage(context.Background(), conn, usage))
245
246
drafts, err := db.FindAllDraftUsage(context.Background(), conn)
247
require.NoError(t, err)
248
cleaned := filter(drafts, attributionID)
249
require.Equal(t, 1, len(cleaned))
250
require.Equal(t, updatedDesc, cleaned[0].Description)
251
}
252
253
func TestFindAllDraftUsage(t *testing.T) {
254
conn := dbtest.ConnectForTests(t)
255
256
attributionID := db.NewTeamAttributionID(uuid.New().String())
257
start := time.Date(2022, 7, 1, 0, 0, 0, 0, time.UTC)
258
259
usage1 := dbtest.NewUsage(t, db.Usage{
260
AttributionID: attributionID,
261
EffectiveTime: db.NewVarCharTime(start.Add(2 * time.Hour)),
262
Draft: true,
263
})
264
usage2 := dbtest.NewUsage(t, db.Usage{
265
AttributionID: attributionID,
266
EffectiveTime: db.NewVarCharTime(start.Add(2 * time.Hour)),
267
Draft: true,
268
})
269
usage3 := dbtest.NewUsage(t, db.Usage{
270
AttributionID: attributionID,
271
EffectiveTime: db.NewVarCharTime(start.Add(2 * time.Hour)),
272
Draft: false,
273
})
274
275
dbtest.CreateUsageRecords(t, conn, usage1, usage2, usage3)
276
drafts, err := db.FindAllDraftUsage(context.Background(), conn)
277
require.NoError(t, err)
278
cleaned := filter(drafts, attributionID)
279
require.Equal(t, 2, len(cleaned))
280
for _, usage := range cleaned {
281
require.True(t, usage.Draft)
282
}
283
284
// let's finalize one record
285
usage2.Draft = false
286
require.NoError(t, db.UpdateUsage(context.Background(), conn, usage2))
287
288
drafts, err = db.FindAllDraftUsage(context.Background(), conn)
289
require.NoError(t, err)
290
cleaned = filter(drafts, attributionID)
291
require.Equal(t, 1, len(cleaned))
292
for _, usage := range cleaned {
293
require.True(t, usage.Draft)
294
}
295
}
296
297
func TestCreditCents(t *testing.T) {
298
for _, s := range []struct {
299
value float64
300
expected db.CreditCents
301
expectedAsFloat float64
302
}{
303
{
304
value: 0,
305
expected: 0,
306
expectedAsFloat: 0,
307
},
308
{
309
value: 0.1,
310
expected: 10,
311
expectedAsFloat: 0.1,
312
},
313
{
314
value: 1.1111,
315
expected: 111,
316
expectedAsFloat: 1.11,
317
},
318
{
319
value: 1.4999,
320
expected: 150,
321
expectedAsFloat: 1.50,
322
},
323
{
324
value: 1.500,
325
expected: 150,
326
expectedAsFloat: 1.50,
327
},
328
{
329
value: 1.501,
330
expected: 150,
331
expectedAsFloat: 1.50,
332
},
333
{
334
value: 1.50999,
335
expected: 151,
336
expectedAsFloat: 1.51,
337
},
338
{
339
value: 1.9999,
340
expected: 200,
341
expectedAsFloat: 2.00,
342
},
343
{
344
value: -1.9999,
345
expected: -200,
346
expectedAsFloat: -2.00,
347
},
348
} {
349
cc := db.NewCreditCents(s.value)
350
require.Equal(t, s.expected, cc)
351
require.Equal(t, s.expectedAsFloat, cc.ToCredits())
352
}
353
}
354
355
func TestListBalance(t *testing.T) {
356
teamAttributionID := db.NewTeamAttributionID(uuid.New().String())
357
teamAttributionID2 := db.NewTeamAttributionID(uuid.New().String())
358
359
conn := dbtest.ConnectForTests(t)
360
dbtest.CreateUsageRecords(t, conn,
361
dbtest.NewUsage(t, db.Usage{
362
AttributionID: teamAttributionID,
363
CreditCents: 100,
364
}),
365
dbtest.NewUsage(t, db.Usage{
366
AttributionID: teamAttributionID,
367
CreditCents: 900,
368
}),
369
dbtest.NewUsage(t, db.Usage{
370
AttributionID: teamAttributionID2,
371
CreditCents: 450,
372
}),
373
dbtest.NewUsage(t, db.Usage{
374
AttributionID: teamAttributionID2,
375
CreditCents: -500,
376
Kind: db.InvoiceUsageKind,
377
}),
378
)
379
380
balances, err := db.ListBalance(context.Background(), conn)
381
require.NoError(t, err)
382
require.Contains(t, balances, db.Balance{
383
AttributionID: teamAttributionID,
384
CreditCents: 1000,
385
})
386
require.Contains(t, balances, db.Balance{
387
AttributionID: teamAttributionID2,
388
CreditCents: -50,
389
})
390
}
391
392
func withUserId(id uuid.UUID, usage db.Usage) db.Usage {
393
usage.SetCreditNoteMetaData(db.CreditNoteMetaData{
394
UserID: id.String(),
395
})
396
return usage
397
}
398
399
func TestGetBalance(t *testing.T) {
400
teamAttributionID := db.NewTeamAttributionID(uuid.New().String())
401
teamAttributionID2 := db.NewTeamAttributionID(uuid.New().String())
402
noUsageAttributionID := db.NewTeamAttributionID(uuid.New().String())
403
404
conn := dbtest.ConnectForTests(t)
405
dbtest.CreateUsageRecords(t, conn,
406
dbtest.NewUsage(t, db.Usage{
407
AttributionID: teamAttributionID,
408
CreditCents: 100,
409
}),
410
dbtest.NewUsage(t, db.Usage{
411
AttributionID: teamAttributionID,
412
CreditCents: 900,
413
}),
414
dbtest.NewUsage(t, db.Usage{
415
AttributionID: teamAttributionID2,
416
CreditCents: 450,
417
}),
418
dbtest.NewUsage(t, db.Usage{
419
AttributionID: teamAttributionID2,
420
CreditCents: -500,
421
Kind: db.InvoiceUsageKind,
422
}),
423
)
424
425
teamBalance, err := db.GetBalance(context.Background(), conn, teamAttributionID)
426
require.NoError(t, err)
427
require.EqualValues(t, 1000, int(teamBalance))
428
429
userBalance, err := db.GetBalance(context.Background(), conn, teamAttributionID2)
430
require.NoError(t, err)
431
require.EqualValues(t, -50, int(userBalance))
432
433
noUsageBalance, err := db.GetBalance(context.Background(), conn, noUsageAttributionID)
434
require.NoError(t, err)
435
require.EqualValues(t, 0, int(noUsageBalance))
436
}
437
438