Skip to content

Commit

Permalink
chore: tweak parallelization of CLI, add test (#603)
Browse files Browse the repository at this point in the history
  • Loading branch information
bastiandoetsch authored Jul 25, 2024
1 parent fff14d6 commit 7a0079e
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 10 deletions.
19 changes: 19 additions & 0 deletions application/server/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* © 2024 Snyk Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package server

const nodejsGoof = "https://github.com/snyk-labs/nodejs-goof"
98 changes: 98 additions & 0 deletions application/server/parallelization_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* © 2024 Snyk Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package server

import (
"context"
"fmt"
"os"
"testing"
"time"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/snyk/snyk-ls/application/di"
"github.com/snyk/snyk-ls/internal/product"
"github.com/snyk/snyk-ls/internal/testutil"
"github.com/snyk/snyk-ls/internal/types"
"github.com/snyk/snyk-ls/internal/uri"
)

func Test_Concurrent_CLI_Runs(t *testing.T) {
srv, jsonRPCRecorder := setupServer(t)
c := testutil.SmokeTest(t, false)
c.SetSnykIacEnabled(false)
c.SetSnykOssEnabled(true)
di.Init()

lspClient := srv.Client

// create clones and make them workspace folders
type scanParamsTuple map[product.Product]bool
successfulScans := map[string]scanParamsTuple{}

var workspaceFolders []types.WorkspaceFolder
for i := 0; i < 10; i++ {
dir := t.TempDir()
repo, err := testutil.SetupCustomTestRepo(t, dir, nodejsGoof, "", c.Logger())
require.NoError(t, err)
folder := types.WorkspaceFolder{
Name: fmt.Sprintf("Test Repo %d", i),
Uri: uri.PathToUri(repo),
}
workspaceFolders = append(workspaceFolders, folder)
successfulScans[repo] = scanParamsTuple{}
}

clientParams := types.InitializeParams{
WorkspaceFolders: workspaceFolders,
InitializationOptions: types.Settings{
Endpoint: os.Getenv("SNYK_API"),
Token: os.Getenv("SNYK_TOKEN"),
EnableTrustedFoldersFeature: "false",
FilterSeverity: types.DefaultSeverityFilter(),
AuthenticationMethod: types.TokenAuthentication,
AutomaticAuthentication: "false",
},
}

lspClient.Call(context.Background(), "initialize", clientParams)
lspClient.Call(context.Background(), "initialized", nil)

// check if all scan params were sent
assert.Eventuallyf(t, func() bool {
notificationsByMethod := jsonRPCRecorder.FindNotificationsByMethod("$/snyk.scan")
for _, notification := range notificationsByMethod {
var scanParams types.SnykScanParams
err := notification.UnmarshalParams(&scanParams)
require.NoError(t, err)

if scanParams.Status == types.Success {
successfulScans[scanParams.FolderPath][product.ToProduct(scanParams.Product)] = true
}
}

received := 0
for _, tuple := range successfulScans {
if tuple[product.ProductOpenSource] == c.IsSnykOssEnabled() && tuple[product.ProductInfrastructureAsCode] == c.IsSnykIacEnabled() {
received++
}
}
return received == len(workspaceFolders)
}, time.Minute*5, time.Millisecond*100, "not all scans were successful")
}
14 changes: 7 additions & 7 deletions application/server/server_smoke_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func Test_SmokeInstanceTest(t *testing.T) {
if endpoint == "" {
t.Setenv("SNYK_API", "https://api.snyk.io")
}
runSmokeTest(t, "https://github.com/snyk-labs/nodejs-goof", "0336589", ossFile, codeFile, false, true, endpoint)
runSmokeTest(t, nodejsGoof, "0336589", ossFile, codeFile, false, true, endpoint)
}

func Test_SmokeWorkspaceScan(t *testing.T) {
Expand Down Expand Up @@ -80,7 +80,7 @@ func Test_SmokeWorkspaceScan(t *testing.T) {
tests := []test{
{
name: "OSS_and_Code",
repo: "https://github.com/snyk-labs/nodejs-goof",
repo: nodejsGoof,
commit: "0336589",
file1: ossFile,
file2: codeFile,
Expand All @@ -89,7 +89,7 @@ func Test_SmokeWorkspaceScan(t *testing.T) {
},
{
name: "OSS_and_Code_with_V1_endpoint",
repo: "https://github.com/snyk-labs/nodejs-goof",
repo: nodejsGoof,
commit: "0336589",
file1: ossFile,
file2: codeFile,
Expand All @@ -98,7 +98,7 @@ func Test_SmokeWorkspaceScan(t *testing.T) {
},
{
name: "OSS_and_Code_with_consistent_ignores",
repo: "https://github.com/snyk-labs/nodejs-goof",
repo: nodejsGoof,
commit: "0336589",
file1: ossFile,
file2: codeFile,
Expand Down Expand Up @@ -168,7 +168,7 @@ func Test_SmokeIssueCaching(t *testing.T) {
c.SetSnykIacEnabled(false)
di.Init()

var cloneTargetDirGoof = setupRepoAndInitialize(t, "https://github.com/snyk-labs/nodejs-goof", "0336589", loc, c)
var cloneTargetDirGoof = setupRepoAndInitialize(t, nodejsGoof, "0336589", loc, c)
folderGoof := workspace.Get().GetFolderContaining(cloneTargetDirGoof)

// wait till the whole workspace is scanned
Expand Down Expand Up @@ -230,7 +230,7 @@ func Test_SmokeIssueCaching(t *testing.T) {
c.SetSnykIacEnabled(false)
di.Init()

var cloneTargetDirGoof = setupRepoAndInitialize(t, "https://github.com/snyk-labs/nodejs-goof", "0336589", loc, c)
var cloneTargetDirGoof = setupRepoAndInitialize(t, nodejsGoof, "0336589", loc, c)
folderGoof := workspace.Get().GetFolderContaining(cloneTargetDirGoof)

// wait till the whole workspace is scanned
Expand Down Expand Up @@ -708,7 +708,7 @@ func Test_SmokeSnykCodeFileScan(t *testing.T) {
cleanupChannels()
di.Init()

var cloneTargetDir, err = testutil.SetupCustomTestRepo(t, t.TempDir(), "https://github.com/snyk-labs/nodejs-goof", "0336589", c.Logger())
var cloneTargetDir, err = testutil.SetupCustomTestRepo(t, t.TempDir(), nodejsGoof, "0336589", c.Logger())
defer func(path string) { _ = os.RemoveAll(path) }(cloneTargetDir)
if err != nil {
t.Fatal(err, "Couldn't setup test repo")
Expand Down
2 changes: 1 addition & 1 deletion application/server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1011,7 +1011,7 @@ func Test_IntegrationHoverResults(t *testing.T) {
fakeAuthenticationProvider := di.AuthenticationService().Providers()[0].(*authentication.FakeAuthenticationProvider)
fakeAuthenticationProvider.IsAuthenticated = true

var cloneTargetDir, err = testutil.SetupCustomTestRepo(t, t.TempDir(), "https://github.com/snyk-labs/nodejs-goof", "0336589", c.Logger())
var cloneTargetDir, err = testutil.SetupCustomTestRepo(t, t.TempDir(), nodejsGoof, "0336589", c.Logger())
defer func(path string) { _ = os.RemoveAll(path) }(cloneTargetDir)
if err != nil {
t.Fatal(err, "Couldn't setup test repo")
Expand Down
2 changes: 1 addition & 1 deletion application/server/trust_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ func Test_MultipleFoldersInRootDirWithOnlyOneTrusted(t *testing.T) {
rootDir := t.TempDir()

// create trusted repo
repo1, err := testutil.SetupCustomTestRepo(t, rootDir, "https://github.com/snyk-labs/nodejs-goof", "0336589", c.Logger())
repo1, err := testutil.SetupCustomTestRepo(t, rootDir, nodejsGoof, "0336589", c.Logger())
assert.NoError(t, err)

// create untrusted directory in same rootDir with the exact prefix
Expand Down
5 changes: 4 additions & 1 deletion infrastructure/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ package cli

import (
"context"
"math"
"os"
"os/exec"
"runtime"
"strings"
"sync"
"time"
Expand All @@ -42,7 +44,8 @@ type SnykCli struct {
var Mutex = &sync.Mutex{}

func NewExecutor(c *config.Config, errorReporter error_reporting.ErrorReporter, notifier noti.Notifier) Executor {
concurrencyLimit := 2
// minimum 1 cpu, max cores - 2
concurrencyLimit := int(math.Max(1, float64(runtime.NumCPU()-2)))

return &SnykCli{
errorReporter,
Expand Down
3 changes: 3 additions & 0 deletions infrastructure/oss/cli_scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,9 @@ func (cliScanner *CLIScanner) retrieveIssues(
targetFilePath string,
fileContent []byte,
) []snyk.Issue {
// we are updating the cli scanner maps/attributes in parallel, so we need to lock
cliScanner.mutex.Lock()
defer cliScanner.mutex.Unlock()
issues := convertScanResultToIssues(
res,
targetFilePath,
Expand Down

0 comments on commit 7a0079e

Please sign in to comment.