Skip to content

Commit db8c64e

Browse files
authored
Fix the flakyness of test which verifies there has to be only one npm request at a time (#1026)
1 parent 222917e commit db8c64e

File tree

3 files changed

+48
-30
lines changed

3 files changed

+48
-30
lines changed

internal/project/ata.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ type TypingsInstaller struct {
6161
pendingRunRequestsMu sync.Mutex
6262
}
6363

64+
func (ti *TypingsInstaller) PendingRunRequestsCount() int {
65+
ti.pendingRunRequestsMu.Lock()
66+
defer ti.pendingRunRequestsMu.Unlock()
67+
return len(ti.pendingRunRequests)
68+
}
69+
6470
func (ti *TypingsInstaller) IsKnownTypesPackageName(p *Project, name string) bool {
6571
// We want to avoid looking this up in the registry as that is expensive. So first check that it's actually an NPM package.
6672
validationResult, _, _ := ValidatePackageName(name)

internal/project/ata_test.go

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package project_test
33
import (
44
"slices"
55
"testing"
6+
"time"
67

78
"github.com/microsoft/typescript-go/internal/bundled"
89
"github.com/microsoft/typescript-go/internal/core"
@@ -215,16 +216,12 @@ func TestAta(t *testing.T) {
215216
_, p2 := service.EnsureDefaultProjectForFile("/user/username/projects/project2/app.js")
216217
var installStatuses []project.TypingsInstallerStatus
217218
installStatuses = append(installStatuses, <-host.ServiceOptions.InstallStatus, <-host.ServiceOptions.InstallStatus)
218-
// Order can be non deterministic since they both will run in parallel
219-
assert.Assert(t, slices.Contains(installStatuses, project.TypingsInstallerStatus{
220-
RequestId: 1,
221-
Project: p1,
222-
Status: "Success",
219+
// Order can be non deterministic since they both will run in parallel - not looking into request ID
220+
assert.Assert(t, slices.ContainsFunc(installStatuses, func(s project.TypingsInstallerStatus) bool {
221+
return s.Project == p1 && s.Status == "Success"
223222
}))
224-
assert.Assert(t, slices.Contains(installStatuses, project.TypingsInstallerStatus{
225-
RequestId: 2,
226-
Project: p2,
227-
Status: "Success",
223+
assert.Assert(t, slices.ContainsFunc(installStatuses, func(s project.TypingsInstallerStatus) bool {
224+
return s.Project == p2 && s.Status == "Success"
228225
}))
229226
})
230227

@@ -242,6 +239,7 @@ func TestAta(t *testing.T) {
242239
"typeAcquisition": { "include": ["grunt", "gulp", "commander"] },
243240
}`,
244241
}
242+
expectedP1First := true
245243
service, host := projecttestutil.Setup(files, &projecttestutil.TestTypingsInstaller{
246244
TestTypingsInstallerOptions: projecttestutil.TestTypingsInstallerOptions{
247245
PackageToFile: map[string]string{
@@ -250,31 +248,40 @@ func TestAta(t *testing.T) {
250248
"lodash": "declare const lodash: { x: number }",
251249
"cordova": "declare const cordova: { x: number }",
252250
"grunt": "declare const grunt: { x: number }",
253-
"gulp": "declare const grunt: { x: number }",
251+
"gulp": "declare const gulp: { x: number }",
254252
},
255253
},
256254
TypingsInstallerOptions: project.TypingsInstallerOptions{
257255
ThrottleLimit: 1,
258256
},
259257
})
260258

259+
host.TestOptions.CheckBeforeNpmInstall = func(cwd string, npmInstallArgs []string) {
260+
for {
261+
pendingCount := service.TypingsInstaller().PendingRunRequestsCount()
262+
if pendingCount == 1 {
263+
if slices.Contains(npmInstallArgs, "@types/gulp@latest") {
264+
expectedP1First = false
265+
}
266+
host.TestOptions.CheckBeforeNpmInstall = nil // Stop checking after first run
267+
break
268+
}
269+
assert.NilError(t, t.Context().Err())
270+
time.Sleep(10 * time.Millisecond)
271+
}
272+
}
273+
261274
service.OpenFile("/user/username/projects/project1/app.js", files["/user/username/projects/project1/app.js"].(string), core.ScriptKindJS, "")
262275
service.OpenFile("/user/username/projects/project2/app.js", files["/user/username/projects/project2/app.js"].(string), core.ScriptKindJS, "")
263276
_, p1 := service.EnsureDefaultProjectForFile("/user/username/projects/project1/app.js")
264277
_, p2 := service.EnsureDefaultProjectForFile("/user/username/projects/project2/app.js")
265278
// Order is determinate since second install will run only after completing first one
266279
status := <-host.ServiceOptions.InstallStatus
267-
assert.Equal(t, status, project.TypingsInstallerStatus{
268-
RequestId: 1,
269-
Project: p1,
270-
Status: "Success",
271-
})
280+
assert.Equal(t, status.Project, core.IfElse(expectedP1First, p1, p2))
281+
assert.Equal(t, status.Status, "Success")
272282
status = <-host.ServiceOptions.InstallStatus
273-
assert.Equal(t, status, project.TypingsInstallerStatus{
274-
RequestId: 2,
275-
Project: p2,
276-
Status: "Success",
277-
})
283+
assert.Equal(t, status.Project, core.IfElse(expectedP1First, p2, p1))
284+
assert.Equal(t, status.Status, "Success")
278285
})
279286

280287
t.Run("discover from node_modules", func(t *testing.T) {

internal/testutil/projecttestutil/projecttestutil.go

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ import (
1919
//go:generate go tool github.com/matryer/moq -stub -fmt goimports -pkg projecttestutil -out clientmock_generated.go ../../project Client
2020

2121
type TestTypingsInstallerOptions struct {
22-
TypesRegistry []string
23-
PackageToFile map[string]string
22+
TypesRegistry []string
23+
PackageToFile map[string]string
24+
CheckBeforeNpmInstall func(cwd string, npmInstallArgs []string)
2425
}
2526

2627
type TestTypingsInstaller struct {
@@ -35,7 +36,7 @@ type ProjectServiceHost struct {
3536
output strings.Builder
3637
logger *project.Logger
3738
ClientMock *ClientMock
38-
testOptions *TestTypingsInstallerOptions
39+
TestOptions *TestTypingsInstallerOptions
3940
ServiceOptions *project.ServiceOptions
4041
}
4142

@@ -89,7 +90,7 @@ var _ project.ServiceHost = (*ProjectServiceHost)(nil)
8990
func Setup(files map[string]any, testOptions *TestTypingsInstaller) (*project.Service, *ProjectServiceHost) {
9091
host := newProjectServiceHost(files)
9192
if testOptions != nil {
92-
host.testOptions = &testOptions.TestTypingsInstallerOptions
93+
host.TestOptions = &testOptions.TestTypingsInstallerOptions
9394
}
9495
var throttleLimit int
9596
if testOptions != nil && testOptions.ThrottleLimit != 0 {
@@ -112,7 +113,7 @@ func Setup(files map[string]any, testOptions *TestTypingsInstaller) (*project.Se
112113
}
113114

114115
func (p *ProjectServiceHost) NpmInstall(cwd string, npmInstallArgs []string) ([]byte, error) {
115-
if p.testOptions == nil {
116+
if p.TestOptions == nil {
116117
return nil, nil
117118
}
118119

@@ -127,10 +128,14 @@ func (p *ProjectServiceHost) NpmInstall(cwd string, npmInstallArgs []string) ([]
127128
return nil, err
128129
}
129130

131+
if p.TestOptions.CheckBeforeNpmInstall != nil {
132+
p.TestOptions.CheckBeforeNpmInstall(cwd, npmInstallArgs)
133+
}
134+
130135
for _, atTypesPackageTs := range npmInstallArgs[2 : lenNpmInstallArgs-2] {
131136
// @types/packageName@TsVersionToUse
132137
packageName := atTypesPackageTs[7 : len(atTypesPackageTs)-len(project.TsVersionToUse)-1]
133-
content, ok := p.testOptions.PackageToFile[packageName]
138+
content, ok := p.TestOptions.PackageToFile[packageName]
134139
if !ok {
135140
return nil, fmt.Errorf("content not provided for %s", packageName)
136141
}
@@ -187,12 +192,12 @@ func TypesRegistryConfig() map[string]string {
187192
func (p *ProjectServiceHost) createTypesRegistryFileContent() string {
188193
var builder strings.Builder
189194
builder.WriteString("{\n \"entries\": {")
190-
for index, entry := range p.testOptions.TypesRegistry {
195+
for index, entry := range p.TestOptions.TypesRegistry {
191196
appendTypesRegistryConfig(&builder, index, entry)
192197
}
193-
index := len(p.testOptions.TypesRegistry)
194-
for key := range p.testOptions.PackageToFile {
195-
if !slices.Contains(p.testOptions.TypesRegistry, key) {
198+
index := len(p.TestOptions.TypesRegistry)
199+
for key := range p.TestOptions.PackageToFile {
200+
if !slices.Contains(p.TestOptions.TypesRegistry, key) {
196201
appendTypesRegistryConfig(&builder, index, key)
197202
index++
198203
}

0 commit comments

Comments
 (0)