Skip to content

Commit

Permalink
Add a test for gRPC file imports
Browse files Browse the repository at this point in the history
  • Loading branch information
na-- committed Nov 6, 2020
1 parent 4e6216f commit 5ff9d3b
Showing 1 changed file with 178 additions and 1 deletion.
179 changes: 178 additions & 1 deletion js/runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/test/grpc_testing"
"gopkg.in/guregu/null.v3"

"github.com/loadimpact/k6/core"
Expand All @@ -54,10 +55,12 @@ import (
"github.com/loadimpact/k6/js/modules/k6/ws"
"github.com/loadimpact/k6/lib"
_ "github.com/loadimpact/k6/lib/executor" // TODO: figure out something better
"github.com/loadimpact/k6/lib/fsext"
"github.com/loadimpact/k6/lib/metrics"
"github.com/loadimpact/k6/lib/testutils"
"github.com/loadimpact/k6/lib/testutils/httpmultibin"
"github.com/loadimpact/k6/lib/types"
"github.com/loadimpact/k6/loader"
"github.com/loadimpact/k6/stats"
"github.com/loadimpact/k6/stats/dummy"
)
Expand Down Expand Up @@ -641,7 +644,7 @@ func TestVURunInterruptDoesntPanic(t *testing.T) {
func TestVUIntegrationGroups(t *testing.T) {
r1, err := getSimpleRunner(t, "/script.js", `
var group = require("k6").group;
exports.default = function() {
exports.default = function {
fnOuter();
group("my group", function() {
fnInner();
Expand Down Expand Up @@ -1801,3 +1804,177 @@ func TestVUPanic(t *testing.T) {
})
}
}

type multiFileTestCase struct {
fses map[string]afero.Fs
rtOpts lib.RuntimeOptions
cwd string
script string
expInitErr bool
expVUErr bool
samples chan stats.SampleContainer
vuParams *lib.VUActivationParams
}

func runMultiFileTestCase(t *testing.T, tc multiFileTestCase, tb *httpmultibin.HTTPMultiBin) {
logger := testutils.NewLogger(t)
runner, err := New(
logger,
&loader.SourceData{
URL: &url.URL{Path: tc.cwd + "/script.js", Scheme: "file"},
Data: []byte(tc.script),
},
tc.fses,
tc.rtOpts,
)
if tc.expInitErr {
require.Error(t, err)
return
}
require.NoError(t, err)

options := runner.GetOptions()
require.Empty(t, options.Validate())

vu, err := runner.NewVU(1, tc.samples)
require.NoError(t, err)

jsVU, ok := vu.(*VU)
require.True(t, ok)
jsVU.state.Dialer = tb.Dialer
jsVU.state.TLSConfig = tb.TLSClientConfig

activeVU := vu.Activate(tc.vuParams)

err = activeVU.RunOnce()
if tc.expVUErr {
require.Error(t, err)
} else {
require.NoError(t, err)
}

arc := runner.MakeArchive()
runnerFromArc, err := NewFromArchive(logger, arc, tc.rtOpts)
require.NoError(t, err)
vuFromArc, err := runnerFromArc.NewVU(2, tc.samples)
require.NoError(t, err)
jsVUFromArc, ok := vuFromArc.(*VU)
require.True(t, ok)
jsVUFromArc.state.Dialer = tb.Dialer
jsVUFromArc.state.TLSConfig = tb.TLSClientConfig
activeVUFromArc := jsVUFromArc.Activate(tc.vuParams)
err = activeVUFromArc.RunOnce()
if tc.expVUErr {
require.Error(t, err)
return
}
require.NoError(t, err)
}

func TestComplicatedFileImportsForGRPC(t *testing.T) {
t.Parallel()
tb := httpmultibin.NewHTTPMultiBin(t)
defer tb.Cleanup()

tb.GRPCStub.UnaryCallFunc = func(ctx context.Context, sreq *grpc_testing.SimpleRequest) (
*grpc_testing.SimpleResponse, error,
) {
return &grpc_testing.SimpleResponse{
Username: "foo",
}, nil
}

fs := afero.NewMemMapFs()
protoFile, err := ioutil.ReadFile("../vendor/google.golang.org/grpc/test/grpc_testing/test.proto")
require.NoError(t, err)
require.NoError(t, afero.WriteFile(fs, "/path/to/service.proto", protoFile, 0644))
require.NoError(t, afero.WriteFile(fs, "/path/to/same-dir.proto", []byte(
`syntax = "proto3";package whatever;import "service.proto";`,
), 0644))
require.NoError(t, afero.WriteFile(fs, "/path/subdir.proto", []byte(
`syntax = "proto3";package whatever;import "to/service.proto";`,
), 0644))
require.NoError(t, afero.WriteFile(fs, "/path/to/abs.proto", []byte(
`syntax = "proto3";package whatever;import "/path/to/service.proto";`,
), 0644))

if isWindows {
fs = fsext.NewTrimFilePathSeparatorFs(fs)
}

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
vuParams := &lib.VUActivationParams{
RunContext: ctx, Scenario: "default", Exec: "default",
}

grpcTestCase := func(expInitErr, expVUErr bool, cwd, loadCode string) multiFileTestCase {
script := tb.Replacer.Replace(fmt.Sprintf(`
var grpc = require('k6/net/grpc');
var client = new grpc.Client();
%s // load statements
exports.default = function() {
client.connect('GRPCBIN_ADDR', {timeout: '3s'});
var resp = client.invoke('grpc.testing.TestService/UnaryCall', {})
if (!resp.message || resp.error || resp.message.username !== 'foo') {
throw new Error('unexpected response message: ' + JSON.stringify(resp.message))
}
}
`, loadCode))

return multiFileTestCase{
fses: map[string]afero.Fs{"file": fs, "https": afero.NewMemMapFs()},
rtOpts: lib.RuntimeOptions{CompatibilityMode: null.NewString("base", true)},
samples: make(chan stats.SampleContainer, 100),
cwd: cwd, expInitErr: expInitErr, expVUErr: expVUErr, script: script, vuParams: vuParams,
}
}

testCases := []multiFileTestCase{
grpcTestCase(false, true, "/", `/* no grpc loads */`), // exp VU error with no proto files loaded

// Init errors when the protobuf file can't be loaded
grpcTestCase(true, false, "/", `client.load(null, 'service.proto');`),
grpcTestCase(true, false, "/", `client.load(null, '/wrong/path/to/service.proto');`),
grpcTestCase(true, false, "/", `client.load(['/', '/path/'], 'service.proto');`),

// Direct imports of service.proto
grpcTestCase(false, false, "/", `client.load(null, '/path/to/service.proto');`), // full path should be fine
grpcTestCase(false, false, "/path/to/", `client.load([], 'service.proto');`), // file name from same folder

grpcTestCase(false, false, "/whatever", `client.load(['/path/to/'], 'service.proto');`), // with import paths
grpcTestCase(false, false, "/path", `client.load(['/', '/path/to/'], 'service.proto');`), // with import paths

// Import another file that imports "service.proto" directly
grpcTestCase(true, false, "/", `client.load([], '/path/to/same-dir.proto');`),
grpcTestCase(true, false, "/path/", `client.load([], 'to/same-dir.proto');`),
grpcTestCase(true, false, "/", `client.load(['/path/'], 'to/same-dir.proto');`),
grpcTestCase(false, false, "/path/to/", `client.load([], 'same-dir.proto');`),
grpcTestCase(false, false, "/", `client.load(['/path/to/'], 'same-dir.proto');`),
grpcTestCase(false, false, "/whatever", `client.load(['/other', '/path/to/'], 'same-dir.proto');`),

// Import another file that imports "to/service.proto" directly
grpcTestCase(true, false, "/", `client.load([], '/path/to/subdir.proto');`),
grpcTestCase(false, false, "/path/", `client.load([], 'subdir.proto');`),
grpcTestCase(false, false, "/", `client.load(['/path/'], 'subdir.proto');`),
grpcTestCase(false, false, "/whatever", `client.load(['/other', '/path/'], 'subdir.proto');`),

// Import another file that imports "/path/to/service.proto" directly
grpcTestCase(true, false, "/", `client.load(['/path'], '/path/to/abs.proto');`),
grpcTestCase(false, false, "/", `client.load([], '/path/to/abs.proto');`),
grpcTestCase(false, false, "/whatever", `client.load(['/'], '/path/to/abs.proto');`),
}

for i, tc := range testCases {
i, tc := i, tc
t.Run(fmt.Sprintf("TestCase_%d", i), func(t *testing.T) {
t.Logf(
"CWD: %s, expInitErr: %t, expVUErr: %t, script injected with: `%s`",
tc.cwd, tc.expInitErr, tc.expVUErr, tc.script,
)
runMultiFileTestCase(t, tc, tb)
})
}
}

0 comments on commit 5ff9d3b

Please sign in to comment.