Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moving the experimental grpc module to the core #3490

Merged
merged 4 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ build:
format:
find . -name '*.go' -exec gofmt -s -w {} +

## grpc-server-run: Runs the gRPC server example.
grpc-server-run:
go run -mod=mod examples/grpc_server/*.go

## check-linter-version: Checks if the linter version is the same as the one specified in the linter config.
check-linter-version:
(golangci-lint version | grep "version $(shell head -n 1 .golangci.yml | tr -d '\# ')") || echo "Your installation of golangci-lint is different from the one that is specified in k6's linter config (there it's $(shell head -n 1 .golangci.yml | tr -d '\# ')). Results could be different in the CI."
Expand Down
129 changes: 129 additions & 0 deletions cmd/tests/cmd_run_grpc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
package tests

import (
"os"
"path/filepath"
"testing"

"go.k6.io/k6/cmd"
"go.k6.io/k6/lib/fsext"

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

const projectRootPath = "../../"

// TestGRPCInputOutput runs same k6's scripts that we have in example folder
// it check that output contains/not contains cetane things
func TestGRPCInputOutput(t *testing.T) {
t.Parallel()

tc := map[string]struct {
script string
outputShouldContain []string
outputShouldNotContain []string
}{
"Server streaming": {
script: projectRootPath + "examples/grpc_server_streaming.js",
outputShouldContain: []string{
"output: -",
"default: 1 iterations for each of 1 VUs",
"1 complete and 0 interrupted iterations",
"Found feature called",
"grpc_streams",
"grpc_streams_msgs_received",
"grpc_streams_msgs_sent",
"All done",
},
outputShouldNotContain: []string{
"Stream Error:",
},
},
"Client Streaming": {
script: projectRootPath + "examples/grpc_client_streaming.js",
outputShouldContain: []string{
"output: -",
"default: 1 iterations for each of 1 VUs",
"1 complete and 0 interrupted iterations",
"Visiting point",
"Finished trip with 5 points",
"Passed 5 feature",
"grpc_streams",
"grpc_streams_msgs_received",
"grpc_streams_msgs_sent",
"All done",
},
outputShouldNotContain: []string{
"Stream Error:",
},
},
"Invoke": {
script: projectRootPath + "examples/grpc_invoke.js",
outputShouldContain: []string{
"output: -",
"default: 1 iterations for each of 1 VUs",
"1 complete and 0 interrupted iterations",
"3 Hasta Way, Newton, NJ 07860, USA",
},
outputShouldNotContain: []string{
"grpc_streams",
"grpc_streams_msgs_received",
"grpc_streams_msgs_sent",
},
},
"Reflection": {
script: projectRootPath + "examples/grpc_reflection.js",
outputShouldContain: []string{
"output: -",
"default: 1 iterations for each of 1 VUs",
"1 complete and 0 interrupted iterations",
"3 Hasta Way, Newton, NJ 07860, USA",
},
outputShouldNotContain: []string{
"grpc_streams",
"grpc_streams_msgs_received",
"grpc_streams_msgs_sent",
},
},
}

// Read the proto file from the testutils package
// it's same that we use in the examples
proto, err := os.ReadFile(projectRootPath + "lib/testutils/grpcservice/route_guide.proto") //nolint:forbidigo
require.NoError(t, err)

for name, test := range tc {
name := name
test := test

t.Run(name, func(t *testing.T) {
t.Parallel()

tb := NewGRPC(t)

script, err := os.ReadFile(test.script) //nolint:forbidigo
require.NoError(t, err)

ts := getSingleFileTestState(t, string(script), []string{"-v", "--log-output=stdout", "--no-usage-report"}, 0)
ts.Env = map[string]string{
"GRPC_ADDR": tb.Addr,
"GRPC_PROTO_PATH": "./proto.proto",
}
require.NoError(t, fsext.WriteFile(ts.FS, filepath.Join(ts.Cwd, "proto.proto"), proto, 0o644))

cmd.ExecuteWithGlobalState(ts.GlobalState)

stdout := ts.Stdout.String()

for _, s := range test.outputShouldContain {
assert.Contains(t, stdout, s)
}
for _, s := range test.outputShouldNotContain {
assert.NotContains(t, stdout, s)
}

assert.Empty(t, ts.Stderr.String())
})
}
}
52 changes: 52 additions & 0 deletions cmd/tests/grpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package tests

import (
"net"
"strings"
"testing"

"go.k6.io/k6/lib/testutils/grpcservice"

"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)

// GRPC .
type GRPC struct {
Addr string
ServerGRPC *grpc.Server
Replacer *strings.Replacer
}

// NewGRPC .
func NewGRPC(t testing.TB) *GRPC {
grpcServer := grpc.NewServer()

addr := getFreeBindAddr(t)

lis, err := net.Listen("tcp", addr)
if err != nil {
t.Fatalf("failed to listen: %v", err)
}

features := grpcservice.LoadFeatures("")
grpcservice.RegisterRouteGuideServer(grpcServer, grpcservice.NewRouteGuideServer(features...))
grpcservice.RegisterFeatureExplorerServer(grpcServer, grpcservice.NewFeatureExplorerServer(features...))
reflection.Register(grpcServer)

go func() {
_ = grpcServer.Serve(lis)
}()

t.Cleanup(func() {
grpcServer.Stop()
})

return &GRPC{
Addr: addr,
ServerGRPC: grpcServer,
Replacer: strings.NewReplacer(
"GRPCBIN_ADDR", addr,
),
}
}
21 changes: 0 additions & 21 deletions examples/grpc.js

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Client, Stream } from 'k6/experimental/grpc';
import { Client, Stream } from 'k6/net/grpc';
import { sleep } from 'k6';

const COORD_FACTOR = 1e7;
Expand All @@ -7,7 +7,7 @@ const COORD_FACTOR = 1e7;
// go run -mod=mod examples/grpc_server/*.go
// (golang should be installed)
const GRPC_ADDR = __ENV.GRPC_ADDR || '127.0.0.1:10000';
const GRPC_PROTO_PATH = __ENV.GRPC_PROTO_PATH || '../../grpc_server/route_guide.proto';
const GRPC_PROTO_PATH = __ENV.GRPC_PROTO_PATH || '../lib/testutils/grpcservice/route_guide.proto';

let client = new Client();
client.load([], GRPC_PROTO_PATH);
Expand Down Expand Up @@ -97,8 +97,6 @@ export default () => {

// close the client stream
stream.end();

sleep(1);
};

const pointSender = (stream, point) => {
Expand Down
28 changes: 28 additions & 0 deletions examples/grpc_invoke.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import grpc from 'k6/net/grpc';
import { check } from "k6";

// to run this sample, you need to start the grpc server first.
// to start the grpc server, run the following command in k6 repository's root:
// go run -mod=mod examples/grpc_server/*.go
// (golang should be installed)
const GRPC_ADDR = __ENV.GRPC_ADDR || '127.0.0.1:10000';
const GRPC_PROTO_PATH = __ENV.GRPC_PROTO_PATH || '../lib/testutils/grpcservice/route_guide.proto';

let client = new grpc.Client();

client.load([], GRPC_PROTO_PATH);

export default () => {
client.connect(GRPC_ADDR, { plaintext: true });

const response = client.invoke("main.FeatureExplorer/GetFeature", {
latitude: 410248224,
longitude: -747127767
})

check(response, { "status is OK": (r) => r && r.status === grpc.StatusOK });
console.log(JSON.stringify(response.message))

client.close()
}

25 changes: 15 additions & 10 deletions examples/grpc_reflection.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import grpc from 'k6/net/grpc';
import {check} from "k6";

// to run this sample, you need to start the grpc server first.
// to start the grpc server, run the following command in k6 repository's root:
// go run -mod=mod examples/grpc_server/*.go
// (golang should be installed)
const GRPC_ADDR = __ENV.GRPC_ADDR || '127.0.0.1:10000';

let client = new grpc.Client();

export default () => {
client.connect("127.0.0.1:10000", {plaintext: true, reflect: true})
const response = client.invoke("main.FeatureExplorer/GetFeature", {
latitude: 410248224,
longitude: -747127767
})

check(response, {"status is OK": (r) => r && r.status === grpc.StatusOK});
console.log(JSON.stringify(response.message))
client.connect(GRPC_ADDR, { plaintext: true, reflect: true });
const response = client.invoke('main.FeatureExplorer/GetFeature', {
latitude: 410248224,
longitude: -747127767,
});

client.close()
}
check(response, { 'status is OK': (r) => r && r.status === grpc.StatusOK });
console.log(JSON.stringify(response.message));

client.close();
};
5 changes: 4 additions & 1 deletion examples/grpc_server/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ module go.k6.io/k6/examples/grpc_server

go 1.19

replace go.k6.io/k6 => ../../

require (
go.k6.io/k6 v0.0.0-00010101000000-000000000000
google.golang.org/grpc v1.58.3
google.golang.org/protobuf v1.31.0
)

require (
Expand All @@ -13,4 +15,5 @@ require (
golang.org/x/sys v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231009173412-8bfb1ae86b6c // indirect
google.golang.org/protobuf v1.31.0 // indirect
)
Loading