@@ -21,6 +21,7 @@ import (
2121 "github.com/coder/coder/v2/coderd/database/dbgen"
2222 "github.com/coder/coder/v2/coderd/database/dbtestutil"
2323 "github.com/coder/coder/v2/coderd/database/dbtime"
24+ "github.com/coder/coder/v2/coderd/rbac"
2425 "github.com/coder/coder/v2/coderd/util/ptr"
2526 "github.com/coder/coder/v2/codersdk"
2627 "github.com/coder/coder/v2/enterprise/coderd/coderdenttest"
@@ -31,9 +32,13 @@ import (
3132)
3233
3334func verifyQuota (ctx context.Context , t * testing.T , client * codersdk.Client , organizationID string , consumed , total int ) {
35+ verifyQuotaUser (ctx , t , client , organizationID , codersdk .Me , consumed , total )
36+ }
37+
38+ func verifyQuotaUser (ctx context.Context , t * testing.T , client * codersdk.Client , organizationID string , user string , consumed , total int ) {
3439 t .Helper ()
3540
36- got , err := client .WorkspaceQuota (ctx , organizationID , codersdk . Me )
41+ got , err := client .WorkspaceQuota (ctx , organizationID , user )
3742 require .NoError (t , err )
3843 require .EqualValues (t , codersdk.WorkspaceQuota {
3944 Budget : total ,
@@ -43,7 +48,7 @@ func verifyQuota(ctx context.Context, t *testing.T, client *codersdk.Client, org
4348 // Remove this check when the deprecated endpoint is removed.
4449 // This just makes sure the deprecated endpoint is still working
4550 // as intended. It will only work for the default organization.
46- deprecatedGot , err := deprecatedQuotaEndpoint (ctx , client , codersdk . Me )
51+ deprecatedGot , err := deprecatedQuotaEndpoint (ctx , client , user )
4752 require .NoError (t , err , "deprecated endpoint" )
4853 // Only continue to check if the values differ
4954 if deprecatedGot .Budget != got .Budget || deprecatedGot .CreditsConsumed != got .CreditsConsumed {
@@ -300,6 +305,95 @@ func TestWorkspaceQuota(t *testing.T) {
300305 verifyQuota (ctx , t , owner , first .OrganizationID .String (), 0 , 30 )
301306 verifyQuota (ctx , t , owner , second .ID .String (), 0 , 15 )
302307 })
308+
309+ // ManyWorkspaces uses dbfake and dbgen to insert a scenario into the db.
310+ t .Run ("ManyWorkspaces" , func (t * testing.T ) {
311+ t .Parallel ()
312+
313+ owner , db , first := coderdenttest .NewWithDatabase (t , & coderdenttest.Options {
314+ LicenseOptions : & coderdenttest.LicenseOptions {
315+ Features : license.Features {
316+ codersdk .FeatureTemplateRBAC : 1 ,
317+ codersdk .FeatureMultipleOrganizations : 1 ,
318+ },
319+ },
320+ })
321+ client , _ := coderdtest .CreateAnotherUser (t , owner , first .OrganizationID , rbac .RoleOwner ())
322+
323+ // Prepopulate database. Use dbfake as it is quicker and
324+ // easier than the api.
325+ ctx := testutil .Context (t , testutil .WaitLong )
326+
327+ user := dbgen .User (t , db , database.User {})
328+ noise := dbgen .User (t , db , database.User {})
329+
330+ second := dbfake .Organization (t , db ).
331+ Members (user , noise ).
332+ EveryoneAllowance (10 ).
333+ Group (database.Group {
334+ QuotaAllowance : 25 ,
335+ }, user , noise ).
336+ Group (database.Group {
337+ QuotaAllowance : 30 ,
338+ }, noise ).
339+ Do ()
340+
341+ third := dbfake .Organization (t , db ).
342+ Members (noise ).
343+ EveryoneAllowance (7 ).
344+ Do ()
345+
346+ verifyQuotaUser (ctx , t , client , second .Org .ID .String (), user .ID .String (), 0 , 35 )
347+ verifyQuotaUser (ctx , t , client , second .Org .ID .String (), noise .ID .String (), 0 , 65 )
348+
349+ // Workspaces owned by the user
350+ consumed := 0
351+ for i := 0 ; i < 2 ; i ++ {
352+ const cost = 5
353+ dbfake .WorkspaceBuild (t , db ,
354+ database.WorkspaceTable {
355+ OwnerID : user .ID ,
356+ OrganizationID : second .Org .ID ,
357+ }).
358+ Seed (database.WorkspaceBuild {
359+ DailyCost : cost ,
360+ }).Do ()
361+ consumed += cost
362+ }
363+
364+ // Add some noise
365+ // Workspace by the user in the third org
366+ dbfake .WorkspaceBuild (t , db ,
367+ database.WorkspaceTable {
368+ OwnerID : user .ID ,
369+ OrganizationID : third .Org .ID ,
370+ }).
371+ Seed (database.WorkspaceBuild {
372+ DailyCost : 10 ,
373+ }).Do ()
374+
375+ // Workspace by another user in third org
376+ dbfake .WorkspaceBuild (t , db ,
377+ database.WorkspaceTable {
378+ OwnerID : noise .ID ,
379+ OrganizationID : third .Org .ID ,
380+ }).
381+ Seed (database.WorkspaceBuild {
382+ DailyCost : 10 ,
383+ }).Do ()
384+
385+ // Workspace by another user in second org
386+ dbfake .WorkspaceBuild (t , db ,
387+ database.WorkspaceTable {
388+ OwnerID : noise .ID ,
389+ OrganizationID : second .Org .ID ,
390+ }).
391+ Seed (database.WorkspaceBuild {
392+ DailyCost : 10 ,
393+ }).Do ()
394+
395+ verifyQuotaUser (ctx , t , client , second .Org .ID .String (), user .ID .String (), consumed , 35 )
396+ })
303397}
304398
305399// nolint:paralleltest,tparallel // Tests must run serially
0 commit comments