Skip to content

Commit 1dc03bd

Browse files
committed
[usage] Fix flakes by deleting records created by each test, not deleting all
1 parent 20aca36 commit 1dc03bd

File tree

13 files changed

+155
-328
lines changed

13 files changed

+155
-328
lines changed

components/usage/pkg/controller/reconciler_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,10 @@ func TestUsageReconciler_ReconcileTimeRange(t *testing.T) {
147147

148148
for _, scenario := range scenarios {
149149
t.Run(scenario.Name, func(t *testing.T) {
150-
conn := db.ConnectForTests(t)
150+
conn := dbtest.ConnectForTests(t)
151151
require.NoError(t, conn.Create(scenario.Memberships).Error)
152-
require.NoError(t, conn.Create(scenario.Workspaces).Error)
153-
require.NoError(t, conn.Create(scenario.Instances).Error)
152+
dbtest.CreateWorkspaces(t, conn, scenario.Workspaces...)
153+
dbtest.CreateWorkspaceInstances(t, conn, scenario.Instances...)
154154

155155
reconciler := &UsageReconciler{
156156
billingController: &NoOpBillingController{},

components/usage/pkg/db/conn.go

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,9 @@ import (
99
"github.com/gitpod-io/gitpod/common-go/log"
1010
driver_mysql "github.com/go-sql-driver/mysql"
1111
"github.com/sirupsen/logrus"
12-
"github.com/stretchr/testify/require"
1312
"gorm.io/driver/mysql"
1413
"gorm.io/gorm"
1514
"gorm.io/gorm/logger"
16-
"testing"
1715
"time"
1816
)
1917

@@ -58,39 +56,3 @@ func Connect(p ConnectionParams) (*gorm.DB, error) {
5856
}),
5957
})
6058
}
61-
62-
func ConnectForTests(t *testing.T) *gorm.DB {
63-
t.Helper()
64-
65-
// These are static connection details for tests, started by `leeway components/usage:init-testdb`.
66-
// We use the same static credentials for CI & local instance of MySQL Server.
67-
conn, err := Connect(ConnectionParams{
68-
User: "root",
69-
Password: "test",
70-
Host: "localhost:23306",
71-
Database: "gitpod",
72-
})
73-
require.NoError(t, err, "Failed to establish connection to DB. In a workspace, run `leeway build components/usage:init-testdb` once to bootstrap the DB.")
74-
75-
t.Cleanup(func() {
76-
// Delete records for known models from the DB
77-
log.Info("Cleaning up DB between connections.")
78-
for _, model := range []interface{}{
79-
&WorkspaceInstance{},
80-
&Workspace{},
81-
&Project{},
82-
&Team{},
83-
&TeamMembership{},
84-
} {
85-
// See https://gorm.io/docs/delete.html#Block-Global-Delete
86-
tx := conn.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(model)
87-
require.NoError(t, tx.Error)
88-
}
89-
90-
rawConn, err := conn.DB()
91-
require.NoError(t, err)
92-
require.NoError(t, rawConn.Close(), "must close database connection")
93-
})
94-
95-
return conn
96-
}

components/usage/pkg/db/conn_test.go

Lines changed: 0 additions & 16 deletions
This file was deleted.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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 dbtest
6+
7+
import (
8+
"github.com/gitpod-io/gitpod/usage/pkg/db"
9+
"github.com/stretchr/testify/require"
10+
"gorm.io/gorm"
11+
"sync"
12+
"testing"
13+
)
14+
15+
var (
16+
connLock = sync.Mutex{}
17+
conn *gorm.DB
18+
)
19+
20+
func ConnectForTests(t *testing.T) *gorm.DB {
21+
t.Helper()
22+
23+
connLock.Lock()
24+
defer connLock.Unlock()
25+
26+
if conn != nil {
27+
return conn
28+
}
29+
30+
// These are static connection details for tests, started by `leeway components/usage:init-testdb`.
31+
// We use the same static credentials for CI & local instance of MySQL Server.
32+
var err error
33+
conn, err = db.Connect(db.ConnectionParams{
34+
User: "root",
35+
Password: "test",
36+
Host: "localhost:23306",
37+
Database: "gitpod",
38+
})
39+
require.NoError(t, err, "Failed to establish connection to DB. In a workspace, run `leeway build components/usage:init-testdb` once to bootstrap the DB.")
40+
41+
return conn
42+
}

components/usage/pkg/db/dbtest/workspace.go

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
package dbtest
66

77
import (
8-
"fmt"
8+
"github.com/gitpod-io/gitpod/common-go/namegen"
99
"github.com/gitpod-io/gitpod/usage/pkg/db"
1010
"github.com/google/uuid"
11-
"math/rand"
11+
"github.com/stretchr/testify/require"
12+
"gorm.io/gorm"
1213
"testing"
1314
)
1415

@@ -64,15 +65,26 @@ func NewWorkspace(t *testing.T, workspace db.Workspace) db.Workspace {
6465
}
6566

6667
func GenerateWorkspaceID() string {
67-
return fmt.Sprintf("gitpodio-gitpod-%s", randSeq(11))
68+
id, _ := namegen.GenerateWorkspaceID()
69+
return id
6870
}
6971

70-
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
72+
func CreateWorkspaces(t *testing.T, conn *gorm.DB, workspaces ...db.Workspace) []db.Workspace {
73+
t.Helper()
7174

72-
func randSeq(n int) string {
73-
b := make([]rune, n)
74-
for i := range b {
75-
b[i] = letters[rand.Intn(len(letters))]
75+
var records []db.Workspace
76+
var ids []string
77+
for _, w := range workspaces {
78+
record := NewWorkspace(t, w)
79+
records = append(records, record)
80+
ids = append(ids, record.ID)
7681
}
77-
return string(b)
82+
83+
require.NoError(t, conn.CreateInBatches(&records, 1000).Error)
84+
85+
t.Cleanup(func() {
86+
require.NoError(t, conn.Where(ids).Delete(&db.Workspace{}).Error)
87+
})
88+
89+
return records
7890
}

components/usage/pkg/db/dbtest/workspace_instance.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import (
88
"database/sql"
99
"github.com/gitpod-io/gitpod/usage/pkg/db"
1010
"github.com/google/uuid"
11+
"github.com/stretchr/testify/require"
12+
"gorm.io/gorm"
1113
"testing"
1214
"time"
1315
)
@@ -87,3 +89,23 @@ func NewWorkspaceInstance(t *testing.T, instance db.WorkspaceInstance) db.Worksp
8789
PhasePersisted: "",
8890
}
8991
}
92+
93+
func CreateWorkspaceInstances(t *testing.T, conn *gorm.DB, instances ...db.WorkspaceInstance) []db.WorkspaceInstance {
94+
t.Helper()
95+
96+
var records []db.WorkspaceInstance
97+
var ids []string
98+
for _, instance := range instances {
99+
record := NewWorkspaceInstance(t, instance)
100+
records = append(records, record)
101+
ids = append(ids, record.ID.String())
102+
}
103+
104+
require.NoError(t, conn.CreateInBatches(&records, 1000).Error)
105+
106+
t.Cleanup(func() {
107+
require.NoError(t, conn.Where(ids).Delete(&db.WorkspaceInstance{}).Error)
108+
})
109+
110+
return records
111+
}

components/usage/pkg/db/project_test.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package db_test
77
import (
88
"fmt"
99
"github.com/gitpod-io/gitpod/usage/pkg/db"
10+
"github.com/gitpod-io/gitpod/usage/pkg/db/dbtest"
1011
"github.com/google/uuid"
1112
"github.com/stretchr/testify/require"
1213
"gorm.io/gorm"
@@ -15,7 +16,7 @@ import (
1516
)
1617

1718
var projectJSON = map[string]interface{}{
18-
"id": "49b5d309-bb95-4a79-846c-e3cf42c0d591",
19+
"id": uuid.New().String(),
1920
"cloneUrl": "https://github.com/gptest1/gptest1-repo1-private.git",
2021
"teamId": "0e433063-1358-4892-9ed2-68e273d17d07",
2122
"appInstallationId": "20446411",
@@ -31,7 +32,7 @@ var projectJSON = map[string]interface{}{
3132
}
3233

3334
func TestProject_ReadExistingRecords(t *testing.T) {
34-
conn := db.ConnectForTests(t)
35+
conn := dbtest.ConnectForTests(t)
3536

3637
id := insertRawProject(t, conn, projectJSON)
3738

@@ -42,6 +43,7 @@ func TestProject_ReadExistingRecords(t *testing.T) {
4243
require.Equal(t, id, project.ID)
4344
require.Equal(t, projectJSON["teamId"], project.TeamID.String)
4445
require.Equal(t, stringToVarchar(t, "2021-11-01T19:36:07.532Z"), project.CreationTime)
46+
require.NoError(t, conn.Where("id = ?", project.ID).Delete(&db.Project{}).Error)
4547
}
4648

4749
func insertRawProject(t *testing.T, conn *gorm.DB, obj map[string]interface{}) uuid.UUID {

components/usage/pkg/db/team_membership_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ package db_test
77
import (
88
"context"
99
"github.com/gitpod-io/gitpod/usage/pkg/db"
10+
"github.com/gitpod-io/gitpod/usage/pkg/db/dbtest"
1011
"github.com/google/uuid"
1112
"github.com/stretchr/testify/require"
1213
"testing"
1314
)
1415

1516
func TestTeamMembership_WriteRead(t *testing.T) {
16-
conn := db.ConnectForTests(t)
17+
conn := dbtest.ConnectForTests(t)
1718

1819
membership := &db.TeamMembership{
1920
ID: uuid.New(),
@@ -33,7 +34,7 @@ func TestTeamMembership_WriteRead(t *testing.T) {
3334
}
3435

3536
func TestListTeamMembershipsForUserIDs(t *testing.T) {
36-
conn := db.ConnectForTests(t)
37+
conn := dbtest.ConnectForTests(t)
3738
userWithTwoTeams := uuid.New()
3839
memberships := []db.TeamMembership{
3940
{

components/usage/pkg/db/team_test.go

Lines changed: 0 additions & 56 deletions
This file was deleted.

components/usage/pkg/db/types_test.go

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package db
66

77
import (
88
"github.com/stretchr/testify/require"
9-
"gorm.io/gorm"
109
"testing"
1110
"time"
1211
)
@@ -116,43 +115,3 @@ func TestVarcharTime_String_ISO8601(t *testing.T) {
116115
require.Equal(t, scenario.Expected, scenario.Time.String())
117116
}
118117
}
119-
120-
func TestVarcharTime_SerializeAndDeserialize(t *testing.T) {
121-
// Custom table to be able to exercise serialization easily, independent of other models
122-
type VarcharModel struct {
123-
ID int `gorm:"primaryKey"`
124-
Time VarcharTime `gorm:"column:time;type:varchar(255);"`
125-
}
126-
127-
conn := ConnectForTests(t)
128-
require.NoError(t, conn.AutoMigrate(&VarcharModel{}))
129-
130-
conn.Session(&gorm.Session{AllowGlobalUpdate: true}).Delete(&VarcharModel{})
131-
132-
for _, scenario := range []struct {
133-
Description string
134-
Input VarcharModel
135-
Expected VarcharModel
136-
}{
137-
{
138-
Description: "empty value for VarcharTime",
139-
Input: VarcharModel{
140-
ID: 1,
141-
Time: VarcharTime{},
142-
},
143-
Expected: VarcharModel{
144-
ID: 1,
145-
Time: VarcharTime{},
146-
},
147-
},
148-
} {
149-
tx := conn.Create(scenario.Input)
150-
require.NoError(t, tx.Error)
151-
152-
var read VarcharModel
153-
tx = conn.First(&read, scenario.Input.ID)
154-
require.NoError(t, tx.Error)
155-
156-
require.Equal(t, scenario.Expected, read)
157-
}
158-
}

0 commit comments

Comments
 (0)