Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
gitpod-io
GitHub Repository: gitpod-io/gitpod
Path: blob/main/components/gitpod-db/go/cost_center_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
"sync"
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
"google.golang.org/grpc/codes"
19
"google.golang.org/grpc/status"
20
"gorm.io/gorm"
21
)
22
23
func TestCostCenter_WriteRead(t *testing.T) {
24
conn := dbtest.ConnectForTests(t)
25
26
costCenter := &db.CostCenter{
27
ID: db.NewTeamAttributionID(uuid.New().String()),
28
SpendingLimit: 100,
29
}
30
cleanUp(t, conn, costCenter.ID)
31
32
tx := conn.Create(costCenter)
33
require.NoError(t, tx.Error)
34
35
read := &db.CostCenter{ID: costCenter.ID}
36
tx = conn.First(read)
37
require.NoError(t, tx.Error)
38
require.Equal(t, costCenter.ID, read.ID)
39
require.Equal(t, costCenter.SpendingLimit, read.SpendingLimit)
40
}
41
42
func TestCostCenterManager_GetOrCreateCostCenter_concurrent(t *testing.T) {
43
conn := dbtest.ConnectForTests(t)
44
mnr := db.NewCostCenterManager(conn, db.DefaultSpendingLimit{
45
ForTeams: 0,
46
ForUsers: 500,
47
})
48
id := db.NewTeamAttributionID(uuid.New().String())
49
cleanUp(t, conn, id)
50
51
waitgroup := &sync.WaitGroup{}
52
save := func() {
53
_, err := mnr.GetOrCreateCostCenter(context.Background(), id)
54
require.NoError(t, err)
55
waitgroup.Done()
56
}
57
waitgroup.Add(10)
58
for i := 0; i < 10; i++ {
59
go save()
60
}
61
waitgroup.Wait()
62
}
63
64
func TestCostCenterManager_GetOrCreateCostCenter(t *testing.T) {
65
conn := dbtest.ConnectForTests(t)
66
mnr := db.NewCostCenterManager(conn, db.DefaultSpendingLimit{
67
ForTeams: 0,
68
ForUsers: 500,
69
})
70
team := db.NewTeamAttributionID(uuid.New().String())
71
cleanUp(t, conn, team)
72
73
teamCC, err := mnr.GetOrCreateCostCenter(context.Background(), team)
74
require.NoError(t, err)
75
t.Cleanup(func() {
76
conn.Model(&db.CostCenter{}).Delete(teamCC)
77
})
78
require.Equal(t, int32(0), teamCC.SpendingLimit)
79
}
80
81
func TestCostCenterManager_GetOrCreateCostCenter_ResetsExpired(t *testing.T) {
82
conn := dbtest.ConnectForTests(t)
83
mnr := db.NewCostCenterManager(conn, db.DefaultSpendingLimit{
84
ForTeams: 0,
85
ForUsers: 500,
86
})
87
88
now := time.Now().UTC()
89
ts := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), 0, time.UTC)
90
expired := ts.Add(-1 * time.Minute)
91
unexpired := ts.Add(1 * time.Minute)
92
93
expiredCC := db.CostCenter{
94
ID: db.NewTeamAttributionID(uuid.New().String()),
95
CreationTime: db.NewVarCharTime(now),
96
SpendingLimit: 0,
97
BillingStrategy: db.CostCenter_Other,
98
NextBillingTime: db.NewVarCharTime(expired),
99
BillingCycleStart: db.NewVarCharTime(now),
100
}
101
unexpiredCC := db.CostCenter{
102
ID: db.NewTeamAttributionID(uuid.New().String()),
103
CreationTime: db.NewVarCharTime(now),
104
SpendingLimit: 500,
105
BillingStrategy: db.CostCenter_Other,
106
NextBillingTime: db.NewVarCharTime(unexpired),
107
BillingCycleStart: db.NewVarCharTime(now),
108
}
109
// Stripe billing strategy should not be reset
110
stripeCC := db.CostCenter{
111
ID: db.NewTeamAttributionID(uuid.New().String()),
112
CreationTime: db.NewVarCharTime(now),
113
SpendingLimit: 0,
114
BillingStrategy: db.CostCenter_Stripe,
115
NextBillingTime: db.VarcharTime{},
116
BillingCycleStart: db.NewVarCharTime(now),
117
}
118
119
dbtest.CreateCostCenters(t, conn,
120
dbtest.NewCostCenter(t, expiredCC),
121
dbtest.NewCostCenter(t, unexpiredCC),
122
dbtest.NewCostCenter(t, stripeCC),
123
)
124
125
// expired db.CostCenter should be reset, so we get a new CreationTime
126
retrievedExpiredCC, err := mnr.GetOrCreateCostCenter(context.Background(), expiredCC.ID)
127
require.NoError(t, err)
128
t.Cleanup(func() {
129
conn.Model(&db.CostCenter{}).Delete(retrievedExpiredCC.ID)
130
})
131
require.Equal(t, db.NewVarCharTime(expired).Time().AddDate(0, 1, 0), retrievedExpiredCC.NextBillingTime.Time())
132
require.Equal(t, expiredCC.ID, retrievedExpiredCC.ID)
133
require.Equal(t, expiredCC.BillingStrategy, retrievedExpiredCC.BillingStrategy)
134
require.WithinDuration(t, now, expiredCC.CreationTime.Time(), 3*time.Second, "new cost center creation time must be within 3 seconds of now")
135
136
// unexpired cost center must not be reset
137
retrievedUnexpiredCC, err := mnr.GetOrCreateCostCenter(context.Background(), unexpiredCC.ID)
138
require.NoError(t, err)
139
require.Equal(t, db.NewVarCharTime(unexpired).Time(), retrievedUnexpiredCC.NextBillingTime.Time())
140
require.Equal(t, unexpiredCC.ID, retrievedUnexpiredCC.ID)
141
require.Equal(t, unexpiredCC.BillingStrategy, retrievedUnexpiredCC.BillingStrategy)
142
require.WithinDuration(t, unexpiredCC.CreationTime.Time(), retrievedUnexpiredCC.CreationTime.Time(), 100*time.Millisecond)
143
144
// stripe cost center must not be reset
145
retrievedStripeCC, err := mnr.GetOrCreateCostCenter(context.Background(), stripeCC.ID)
146
require.NoError(t, err)
147
require.False(t, retrievedStripeCC.NextBillingTime.IsSet())
148
require.Equal(t, stripeCC.ID, retrievedStripeCC.ID)
149
require.Equal(t, stripeCC.BillingStrategy, retrievedStripeCC.BillingStrategy)
150
require.WithinDuration(t, stripeCC.CreationTime.Time(), retrievedStripeCC.CreationTime.Time(), 100*time.Millisecond)
151
}
152
153
func TestCostCenterManager_UpdateCostCenter(t *testing.T) {
154
conn := dbtest.ConnectForTests(t)
155
limits := db.DefaultSpendingLimit{
156
ForTeams: 0,
157
ForUsers: 500,
158
MinForUsersOnStripe: 1000,
159
}
160
161
t.Run("prevents updates to negative spending limit", func(t *testing.T) {
162
mnr := db.NewCostCenterManager(conn, limits)
163
teamAttributionID := db.NewTeamAttributionID(uuid.New().String())
164
cleanUp(t, conn, teamAttributionID)
165
166
_, err := mnr.UpdateCostCenter(context.Background(), db.CostCenter{
167
ID: teamAttributionID,
168
BillingStrategy: db.CostCenter_Stripe,
169
SpendingLimit: -1,
170
})
171
require.Error(t, err)
172
require.Equal(t, codes.InvalidArgument, status.Code(err))
173
})
174
175
t.Run("team on Stripe billing strategy can set arbitrary positive spending limit", func(t *testing.T) {
176
mnr := db.NewCostCenterManager(conn, limits)
177
teamAttributionID := db.NewTeamAttributionID(uuid.New().String())
178
cleanUp(t, conn, teamAttributionID)
179
180
// Allows udpating cost center as long as spending limit remains as configured
181
res, err := mnr.UpdateCostCenter(context.Background(), db.CostCenter{
182
ID: teamAttributionID,
183
BillingStrategy: db.CostCenter_Stripe,
184
SpendingLimit: limits.ForTeams,
185
})
186
require.NoError(t, err)
187
requireCostCenterEqual(t, db.CostCenter{
188
ID: teamAttributionID,
189
BillingStrategy: db.CostCenter_Stripe,
190
SpendingLimit: limits.ForTeams,
191
}, res)
192
193
// Allows updating cost center to any positive value
194
_, err = mnr.UpdateCostCenter(context.Background(), db.CostCenter{
195
ID: teamAttributionID,
196
BillingStrategy: db.CostCenter_Stripe,
197
SpendingLimit: 10,
198
})
199
require.NoError(t, err)
200
})
201
202
t.Run("increment billing cycle should always increment to now", func(t *testing.T) {
203
mnr := db.NewCostCenterManager(conn, limits)
204
teamAttributionID := db.NewTeamAttributionID(uuid.New().String())
205
cleanUp(t, conn, teamAttributionID)
206
207
res, err := mnr.GetOrCreateCostCenter(context.Background(), teamAttributionID)
208
require.NoError(t, err)
209
210
// set res.nextBillingTime to two months ago
211
res.NextBillingTime = db.NewVarCharTime(time.Now().AddDate(0, -2, 0))
212
conn.Save(res)
213
214
cc, err := mnr.IncrementBillingCycle(context.Background(), teamAttributionID)
215
require.NoError(t, err)
216
217
require.True(t, cc.NextBillingTime.Time().After(time.Now()), "The next billing time should be in the future")
218
require.True(t, cc.BillingCycleStart.Time().Before(time.Now()), "The next billing time should be in the future")
219
})
220
}
221
222
func TestSaveCostCenterMovedToStripe(t *testing.T) {
223
conn := dbtest.ConnectForTests(t)
224
mnr := db.NewCostCenterManager(conn, db.DefaultSpendingLimit{
225
ForTeams: 20,
226
ForUsers: 500,
227
})
228
team := db.NewTeamAttributionID(uuid.New().String())
229
cleanUp(t, conn, team)
230
teamCC, err := mnr.GetOrCreateCostCenter(context.Background(), team)
231
require.NoError(t, err)
232
require.Equal(t, int32(20), teamCC.SpendingLimit)
233
234
teamCC.BillingStrategy = db.CostCenter_Stripe
235
teamCC.SpendingLimit = 400050
236
teamCC, err = mnr.UpdateCostCenter(context.Background(), teamCC)
237
require.NoError(t, err)
238
require.Equal(t, db.CostCenter_Stripe, teamCC.BillingStrategy)
239
require.Equal(t, teamCC.CreationTime.Time().AddDate(0, 1, 0), teamCC.NextBillingTime.Time())
240
require.Equal(t, int32(400050), teamCC.SpendingLimit)
241
242
teamCC.BillingStrategy = db.CostCenter_Other
243
teamCC, err = mnr.UpdateCostCenter(context.Background(), teamCC)
244
require.NoError(t, err)
245
require.Equal(t, teamCC.CreationTime.Time().AddDate(0, 1, 0).Truncate(time.Second), teamCC.NextBillingTime.Time().Truncate(time.Second))
246
require.Equal(t, int32(20), teamCC.SpendingLimit)
247
}
248
249
func cleanUp(t *testing.T, conn *gorm.DB, attributionIds ...db.AttributionID) {
250
t.Helper()
251
t.Cleanup(func() {
252
for _, attributionId := range attributionIds {
253
conn.Where("id = ?", string(attributionId)).Delete(&db.CostCenter{})
254
conn.Where("attributionId = ?", string(attributionId)).Delete(&db.Usage{})
255
}
256
})
257
}
258
259
func requireCostCenterEqual(t *testing.T, expected, actual db.CostCenter) {
260
t.Helper()
261
262
// ignore timestamps in comparsion
263
require.Equal(t, expected.ID, actual.ID)
264
require.EqualValues(t, expected.SpendingLimit, actual.SpendingLimit)
265
require.Equal(t, expected.BillingStrategy, actual.BillingStrategy)
266
}
267
268
func TestCostCenter_ListLatestCostCentersWithBillingTimeBefore(t *testing.T) {
269
270
t.Run("no cost centers found when no data exists", func(t *testing.T) {
271
conn := dbtest.ConnectForTests(t)
272
mnr := db.NewCostCenterManager(conn, db.DefaultSpendingLimit{
273
ForTeams: 0,
274
ForUsers: 500,
275
})
276
277
ts := time.Date(2022, 10, 10, 10, 10, 10, 10, time.UTC)
278
279
retrieved, err := mnr.ListManagedCostCentersWithBillingTimeBefore(context.Background(), ts.Add(7*24*time.Hour))
280
require.NoError(t, err)
281
require.Len(t, retrieved, 0)
282
})
283
284
t.Run("returns the most recent cost center (by creation time)", func(t *testing.T) {
285
conn := dbtest.ConnectForTests(t)
286
mnr := db.NewCostCenterManager(conn, db.DefaultSpendingLimit{
287
ForTeams: 0,
288
ForUsers: 500,
289
})
290
291
attributionID := uuid.New().String()
292
firstCreation := time.Date(2022, 10, 10, 10, 10, 10, 10, time.UTC)
293
secondCreation := firstCreation.Add(24 * time.Hour)
294
295
costCenters := []db.CostCenter{
296
dbtest.NewCostCenter(t, db.CostCenter{
297
ID: db.NewTeamAttributionID(attributionID),
298
SpendingLimit: 100,
299
CreationTime: db.NewVarCharTime(firstCreation),
300
BillingStrategy: db.CostCenter_Other,
301
NextBillingTime: db.NewVarCharTime(firstCreation),
302
}),
303
dbtest.NewCostCenter(t, db.CostCenter{
304
ID: db.NewTeamAttributionID(attributionID),
305
SpendingLimit: 100,
306
CreationTime: db.NewVarCharTime(secondCreation),
307
BillingStrategy: db.CostCenter_Other,
308
NextBillingTime: db.NewVarCharTime(secondCreation),
309
}),
310
}
311
312
dbtest.CreateCostCenters(t, conn, costCenters...)
313
314
retrieved, err := mnr.ListManagedCostCentersWithBillingTimeBefore(context.Background(), secondCreation.Add(7*24*time.Hour))
315
require.NoError(t, err)
316
require.Len(t, retrieved, 1)
317
318
requireCostCenterEqual(t, costCenters[1], retrieved[0])
319
})
320
321
t.Run("returns results only when most recent cost center matches billing strategy", func(t *testing.T) {
322
conn := dbtest.ConnectForTests(t)
323
mnr := db.NewCostCenterManager(conn, db.DefaultSpendingLimit{
324
ForTeams: 0,
325
ForUsers: 500,
326
})
327
328
attributionID := uuid.New().String()
329
firstCreation := time.Date(2022, 10, 10, 10, 10, 10, 10, time.UTC)
330
secondCreation := firstCreation.Add(24 * time.Hour)
331
332
costCenters := []db.CostCenter{
333
dbtest.NewCostCenter(t, db.CostCenter{
334
ID: db.NewTeamAttributionID(attributionID),
335
SpendingLimit: 100,
336
CreationTime: db.NewVarCharTime(firstCreation),
337
BillingStrategy: db.CostCenter_Other,
338
NextBillingTime: db.NewVarCharTime(firstCreation),
339
}),
340
dbtest.NewCostCenter(t, db.CostCenter{
341
ID: db.NewTeamAttributionID(attributionID),
342
SpendingLimit: 100,
343
CreationTime: db.NewVarCharTime(secondCreation),
344
BillingStrategy: db.CostCenter_Stripe,
345
}),
346
}
347
348
dbtest.CreateCostCenters(t, conn, costCenters...)
349
350
retrieved, err := mnr.ListManagedCostCentersWithBillingTimeBefore(context.Background(), secondCreation.Add(7*24*time.Hour))
351
require.NoError(t, err)
352
require.Len(t, retrieved, 0)
353
})
354
}
355
356
func TestCostCenterManager_ResetUsage(t *testing.T) {
357
now := time.Now().UTC()
358
ts := time.Date(now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), 0, time.UTC)
359
360
t.Run("errors when cost center is not Other", func(t *testing.T) {
361
conn := dbtest.ConnectForTests(t)
362
mnr := db.NewCostCenterManager(conn, db.DefaultSpendingLimit{
363
ForTeams: 0,
364
ForUsers: 500,
365
})
366
cc := dbtest.CreateCostCenters(t, conn, db.CostCenter{
367
ID: db.NewTeamAttributionID(uuid.New().String()),
368
CreationTime: db.NewVarCharTime(time.Now()),
369
SpendingLimit: 500,
370
BillingStrategy: db.CostCenter_Stripe,
371
})[0]
372
373
_, err := mnr.ResetUsage(context.Background(), cc.ID)
374
require.Error(t, err)
375
})
376
377
t.Run("resets for teams", func(t *testing.T) {
378
conn := dbtest.ConnectForTests(t)
379
mnr := db.NewCostCenterManager(conn, db.DefaultSpendingLimit{
380
ForTeams: 0,
381
ForUsers: 500,
382
})
383
oldCC := dbtest.CreateCostCenters(t, conn, db.CostCenter{
384
ID: db.NewTeamAttributionID(uuid.New().String()),
385
CreationTime: db.NewVarCharTime(time.Now()),
386
SpendingLimit: 10,
387
BillingStrategy: db.CostCenter_Other,
388
NextBillingTime: db.NewVarCharTime(ts),
389
BillingCycleStart: db.NewVarCharTime(ts.AddDate(0, -1, 0)),
390
})[0]
391
newCC, err := mnr.ResetUsage(context.Background(), oldCC.ID)
392
require.NoError(t, err)
393
require.Equal(t, oldCC.ID, newCC.ID)
394
require.EqualValues(t, 10, newCC.SpendingLimit)
395
require.Equal(t, db.CostCenter_Other, newCC.BillingStrategy)
396
require.Equal(t, db.NewVarCharTime(ts.AddDate(0, 1, 0)).Time(), newCC.NextBillingTime.Time())
397
398
})
399
400
t.Run("transitioning from stripe back to other restores previous limit", func(t *testing.T) {
401
conn := dbtest.ConnectForTests(t)
402
mnr := db.NewCostCenterManager(conn, db.DefaultSpendingLimit{
403
ForTeams: 0,
404
ForUsers: 500,
405
})
406
var originalSpendingLimit int32 = 10
407
cc := dbtest.CreateCostCenters(t, conn, db.CostCenter{
408
ID: db.NewTeamAttributionID(uuid.New().String()),
409
CreationTime: db.NewVarCharTime(time.Now()),
410
SpendingLimit: originalSpendingLimit,
411
BillingStrategy: db.CostCenter_Other,
412
NextBillingTime: db.NewVarCharTime(ts),
413
BillingCycleStart: db.NewVarCharTime(ts.AddDate(0, -1, 0)),
414
})[0]
415
cc.BillingStrategy = db.CostCenter_Stripe
416
_, err := mnr.UpdateCostCenter(context.Background(), cc)
417
require.NoError(t, err)
418
// change spending limit
419
cc.SpendingLimit = int32(20)
420
_, err = mnr.UpdateCostCenter(context.Background(), cc)
421
require.NoError(t, err)
422
423
cc, err = mnr.GetOrCreateCostCenter(context.Background(), cc.ID)
424
require.NoError(t, err)
425
require.Equal(t, int32(20), cc.SpendingLimit)
426
427
// change to other strategy again and verify the original limit is restored
428
cc.BillingStrategy = db.CostCenter_Other
429
cc, err = mnr.UpdateCostCenter(context.Background(), cc)
430
require.NoError(t, err)
431
require.Equal(t, originalSpendingLimit, cc.SpendingLimit)
432
})
433
434
t.Run("users get free credits only once for the first org", func(t *testing.T) {
435
conn := dbtest.ConnectForTests(t)
436
limitForUsers := int32(500)
437
limitForTeams := int32(0)
438
mnr := db.NewCostCenterManager(conn, db.DefaultSpendingLimit{
439
ForTeams: limitForTeams,
440
ForUsers: limitForUsers,
441
})
442
createMembership := func(t *testing.T, anOrgID string, aUserID string) {
443
memberShipID := uuid.New().String()
444
db := conn.Exec(`INSERT INTO d_b_team_membership (id, teamid, userid, role, creationtime) VALUES (?, ?, ?, ?, ?)`,
445
memberShipID,
446
anOrgID,
447
aUserID,
448
"owner",
449
db.TimeToISO8601(time.Now()))
450
require.NoError(t, db.Error)
451
t.Cleanup(func() {
452
conn.Exec(`DELETE FROM d_b_team_membership WHERE id = ?`, memberShipID)
453
})
454
}
455
456
createIdentity := func(t *testing.T, aUserID string, email string) {
457
identityID := uuid.New().String()
458
db := conn.Exec(`INSERT INTO d_b_identity (authProviderID, authId, authName, userid, primaryemail) VALUES (?, ?, ?, ?, ?)`,
459
"gitpod", identityID, "gitpod", aUserID, email)
460
require.NoError(t, db.Error)
461
t.Cleanup(func() {
462
conn.Exec(`DELETE FROM d_b_identity WHERE authId = ?`, identityID)
463
})
464
}
465
466
orgID := uuid.New().String()
467
orgID2 := uuid.New().String()
468
userID := uuid.New().String()
469
t.Cleanup(func() {
470
conn.Exec(`DELETE FROM d_b_free_credits WHERE userId = ?`, userID)
471
})
472
createIdentity(t, userID, "[email protected]")
473
createMembership(t, orgID, userID)
474
createMembership(t, orgID2, userID)
475
cc1, err := mnr.GetOrCreateCostCenter(context.Background(), db.NewTeamAttributionID(orgID))
476
require.NoError(t, err)
477
cc2, err := mnr.GetOrCreateCostCenter(context.Background(), db.NewTeamAttributionID(orgID2))
478
require.NoError(t, err)
479
require.Equal(t, limitForUsers, cc1.SpendingLimit)
480
require.Equal(t, limitForTeams, cc2.SpendingLimit)
481
})
482
483
t.Run("users with same email get free credits only once", func(t *testing.T) {
484
conn := dbtest.ConnectForTests(t)
485
limitForUsers := int32(500)
486
limitForTeams := int32(0)
487
mnr := db.NewCostCenterManager(conn, db.DefaultSpendingLimit{
488
ForTeams: limitForTeams,
489
ForUsers: limitForUsers,
490
})
491
createMembership := func(t *testing.T, anOrgID string, aUserID string) {
492
memberShipID := uuid.New().String()
493
db := conn.Exec(`INSERT INTO d_b_team_membership (id, teamid, userid, role, creationtime) VALUES (?, ?, ?, ?, ?)`,
494
memberShipID,
495
anOrgID,
496
aUserID,
497
"owner",
498
db.TimeToISO8601(time.Now()))
499
require.NoError(t, db.Error)
500
t.Cleanup(func() {
501
conn.Exec(`DELETE FROM d_b_team_membership WHERE id = ?`, memberShipID)
502
})
503
}
504
505
createIdentity := func(t *testing.T, aUserID string, email string) {
506
identityID := uuid.New().String()
507
db := conn.Exec(`INSERT INTO d_b_identity (authProviderID, authId, authName, userid, primaryemail) VALUES (?, ?, ?, ?, ?)`,
508
"gitpod", identityID, "gitpod", aUserID, email)
509
require.NoError(t, db.Error)
510
t.Cleanup(func() {
511
conn.Exec(`DELETE FROM d_b_identity WHERE authId = ?`, identityID)
512
})
513
}
514
515
orgID := uuid.New().String()
516
orgID2 := uuid.New().String()
517
userID := uuid.New().String()
518
userID2 := uuid.New().String()
519
t.Cleanup(func() {
520
conn.Exec(`DELETE FROM d_b_free_credits WHERE userId = ?`, userID)
521
})
522
createIdentity(t, userID, "[email protected]")
523
createIdentity(t, userID2, "[email protected]")
524
createMembership(t, orgID, userID)
525
createMembership(t, orgID2, userID2)
526
cc1, err := mnr.GetOrCreateCostCenter(context.Background(), db.NewTeamAttributionID(orgID))
527
require.NoError(t, err)
528
cc2, err := mnr.GetOrCreateCostCenter(context.Background(), db.NewTeamAttributionID(orgID2))
529
require.NoError(t, err)
530
require.Equal(t, limitForUsers, cc1.SpendingLimit)
531
require.Equal(t, limitForTeams, cc2.SpendingLimit)
532
})
533
}
534
535