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

Add generated code unit test #247

Merged
merged 1 commit into from
Aug 15, 2018
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
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ package_static: nginx_static
plugin:
cd "$(ROOT_DIR)"/javascript/net/grpc/web && make

install-plugin:
cd "$(ROOT_DIR)"/javascript/net/grpc/web && make install

example: plugin
cd "$(ROOT_DIR)"/net/grpc/gateway/examples/echo && make

Expand Down
3 changes: 3 additions & 0 deletions javascript/net/grpc/web/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,8 @@ all: protoc-gen-grpc-web
protoc-gen-grpc-web: grpc_generator.o
$(CXX) $^ $(LDFLAGS) -o $@

install: protoc-gen-grpc-web
install protoc-gen-grpc-web /usr/local/bin/protoc-gen-grpc-web

clean:
rm -f *.o protoc-gen-grpc-web
4 changes: 2 additions & 2 deletions net/grpc/gateway/docker/prereqs/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ RUN cd /github/grpc-web/third_party/grpc && \
RUN cd /github/grpc-web/third_party/grpc/third_party/protobuf && \
make install

RUN cd /github/grpc-web/javascript/net/grpc/web && \
make
RUN cd /github/grpc-web && \
make install-plugin

RUN cd /github/grpc-web/packages/grpc-web && \
npm install && \
Expand Down
26 changes: 20 additions & 6 deletions packages/grpc-web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,26 @@ $ npm i grpc-web
$ yarn add grpc-web
```

2. Generate your client with `protoc` and the `protoc-gen-grpc-web` plugin.
2. Compile the protoc plugin

```sh
$ git clone https://github.com/grpc/grpc-web
$ cd grpc-web && sudo make install-plugin
```

3. Generate your client with `protoc` and the `protoc-gen-grpc-web` plugin.
Make sure you set the `import_style` for both `js_out` and `grpc-web_out` to
**commonjs**. It is also important that both your js and grpc-web output to
the same directory.

```sh
# Compile the protoc-gen-grpc-web plugin
$ git clone https://github.com/grpc/grpc-web
$ cd grpc-web && make plugin

$ protoc -I=$DIR echo.proto \
--plugin=protoc-gen-grpc-web=/path-to/protoc-gen-grpc-web \
--js_out=import_style=commonjs:generated \
--grpc-web_out=import_style=commonjs,mode=grpcwebtext,out=echo_grpc_pb.js:generated
```

3. Start using your generated client!
4. Start using your generated client!

```js
const {EchoRequest} = require('./generated/echo_pb.js');
Expand Down Expand Up @@ -83,3 +86,14 @@ $ docker-compose up echo-server envoy commonjs-client
```

Open your browser to `http://localhost:8081/echotest.html`


## Run tests

Pre-requisites:
- `protoc`
- `protoc-gen-grpc-web` plugin

```sh
$ npm test
```
11 changes: 9 additions & 2 deletions packages/grpc-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@
"description": "gRPC web runtime",
"main": "index.js",
"scripts": {
"build": "node scripts/build.js",
"prepare": "npm run build && require-self",
"prepublishOnly": "npm run build",
"build": "node scripts/build.js"
"test": "mocha"
},
"license": "Apache-2.0",
"devDependencies": {
"google-closure-compiler": "^20180716.0.0"
"command-exists": "^1.2.7",
"google-closure-compiler": "^20180716.0.0",
"google-protobuf": "^3.6.1",
"mocha": "^5.2.0",
"mock-xmlhttprequest": "^2.0.0",
"require-self": "^0.2.1"
}
}
41 changes: 41 additions & 0 deletions packages/grpc-web/test/echo.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2018 Google LLC
//
// 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
//
// https://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.

syntax = "proto3";

package grpc.gateway.testing;

message EchoRequest {
string message = 1;
}

message EchoResponse {
string message = 1;
}

message ServerStreamingEchoRequest {
string message = 1;
int32 message_count = 2;
int32 message_interval = 3;
}

message ServerStreamingEchoResponse {
string message = 1;
}

service EchoService {
rpc Echo(EchoRequest) returns (EchoResponse);
rpc ServerStreamingEcho(ServerStreamingEchoRequest)
returns (stream ServerStreamingEchoResponse);
}
212 changes: 212 additions & 0 deletions packages/grpc-web/test/generated_code_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
const assert = require('assert');
const execSync = require('child_process').execSync;
const commandExists = require('command-exists').sync;
const fs = require('fs');
const path = require('path');

var MockXMLHttpRequest = require('mock-xmlhttprequest').newMockXhr();
global.XMLHttpRequest = MockXMLHttpRequest;


describe('protoc generated code', function() {
const genCodePath = path.resolve(__dirname, './echo_pb.js');
const genCodeCmd = `protoc -I=./test echo.proto \
--js_out=import_style=commonjs:./test`

before(function() {
if (!commandExists('protoc')) {
assert.fail('protoc is not installed');
}
});

beforeEach(function() {
if (fs.existsSync(genCodePath)) {
fs.unlinkSync(genCodePath);
}
});

afterEach(function() {
if (fs.existsSync(genCodePath)) {
fs.unlinkSync(genCodePath);
}
});

it('should exist', function() {
execSync(genCodeCmd);
assert.equal(true, fs.existsSync(genCodePath));
});

it('should import', function() {
execSync(genCodeCmd);
const {EchoRequest} = require(genCodePath);
var req = new EchoRequest();
req.setMessage('abc');
assert.equal('abc', req.getMessage());
});
});


describe('grpc-web plugin generated code (commonjs+grpcwebtext)', function() {
const protoGenCodePath = path.resolve(__dirname, './echo_pb.js');
const genCodePath = path.resolve(__dirname, './echo_grpc_pb.js');
const genCodeCmd = `protoc -I=./test echo.proto \
--js_out=import_style=commonjs:./test \
--grpc-web_out=import_style=commonjs,mode=grpcwebtext,out=echo_grpc_pb.js:\
./test`;

before(function() {
['protoc', 'protoc-gen-grpc-web'].map(prog => {
if (!commandExists(prog)) {
assert.fail(`${prog} is not installed`);
}
});
});

beforeEach(function() {
if (fs.existsSync(protoGenCodePath)) {
fs.unlinkSync(protoGenCodePath);
}
if (fs.existsSync(genCodePath)) {
fs.unlinkSync(genCodePath);
}
});

afterEach(function() {
if (fs.existsSync(protoGenCodePath)) {
fs.unlinkSync(protoGenCodePath);
}
if (fs.existsSync(genCodePath)) {
fs.unlinkSync(genCodePath);
}
});

it('should exist', function() {
execSync(genCodeCmd);
assert.equal(true, fs.existsSync(genCodePath));
});

it('should import', function() {
execSync(genCodeCmd);
const {EchoServiceClient} = require(genCodePath);
var echoService = new EchoServiceClient('Bla', null, null);
assert.equal('function', typeof echoService.echo);
});

it('should send unary request', function(done) {
execSync(genCodeCmd);
const {EchoServiceClient} = require(genCodePath);
const {EchoRequest} = require(protoGenCodePath);
var echoService = new EchoServiceClient('MyHostname', null, null);
var request = new EchoRequest();
request.setMessage('aaa');
MockXMLHttpRequest.onSend = function(xhr) {
assert.equal('POST', xhr.method);
// a single 'aaa' string, encoded
assert.equal('AAAAAAUKA2FhYQ==', xhr.body);
assert.equal('MyHostname/grpc.gateway.testing.EchoService/Echo',
xhr.url);
assert.equal(
`accept: application/grpc-web-text\r\n\
content-type: application/grpc-web-text\r\n\
custom-header-1: value1\r\n\
x-grpc-web: 1\r\n\
x-user-agent: grpc-web-javascript/0.1\r\n`, xhr.requestHeaders.getAll());
done();
};
echoService.echo(request, {'custom-header-1':'value1'});
});

it('should receive unary response', function(done) {
execSync(genCodeCmd);
const {EchoServiceClient} = require(genCodePath);
const {EchoRequest} = require(protoGenCodePath);
var echoService = new EchoServiceClient('MyHostname', null, null);
var request = new EchoRequest();
request.setMessage('aaa');
MockXMLHttpRequest.onSend = function(xhr) {
xhr.respond(200, {'Content-Type': 'application/grpc-web-text'},
// a single data frame with 'aaa' message, encoded
'AAAAAAUKA2FhYQ==');
};
echoService.echo(request, {'custom-header-1':'value1'},
function(err, response) {
assert.equal('aaa', response.getMessage());
done();
});
});

it('should receive streaming response', function(done) {
execSync(genCodeCmd);
const {EchoServiceClient} = require(genCodePath);
const {ServerStreamingEchoRequest} = require(protoGenCodePath);
var echoService = new EchoServiceClient('MyHostname', null, null);
var request = new ServerStreamingEchoRequest();
request.setMessage('aaa');
request.setMessageCount(3);
MockXMLHttpRequest.onSend = function(xhr) {
xhr.respond(200, {'Content-Type': 'application/grpc-web-text'},
// 3 'aaa' messages in 3 data frames, encoded
'AAAAAAUKA2FhYQAAAAAFCgNhYWEAAAAABQoDYWFh');
};
var numMessagesReceived = 0;
var p = new Promise(function(resolve, reject) {
var stream = echoService.serverStreamingEcho(request,
{'custom-header-1':'value1'});
stream.on('data', function(response) {
numMessagesReceived++;
assert.equal('aaa', response.getMessage());
});
stream.on('end', function() {
resolve();
});
});
p.then(function(res) {
assert.equal(3, numMessagesReceived);
done();
});
});

it('should receive trailing metadata', function(done) {
execSync(genCodeCmd);
const {EchoServiceClient} = require(genCodePath);
const {EchoRequest} = require(protoGenCodePath);
var echoService = new EchoServiceClient('MyHostname', null, null);
var request = new EchoRequest();
request.setMessage('aaa');
MockXMLHttpRequest.onSend = function(xhr) {
xhr.respond(200, {'Content-Type': 'application/grpc-web-text'},
// a single data frame with an 'aaa' message, followed by,
// a trailer frame with content 'grpc-status:0'
'AAAAAAUKA2FhYYAAAAAPZ3JwYy1zdGF0dXM6MA0K');
};
var call = echoService.echo(request, {'custom-header-1':'value1'},
function(err, response) {
assert.equal('aaa', response.getMessage());
});
call.on('status', function(status) {
assert.equal('object', typeof status.metadata);
assert.equal(true, 'grpc-status' in status.metadata);
assert.equal(0, parseInt(status.metadata['grpc-status']));
done();
});
});

it('should receive error', function(done) {
execSync(genCodeCmd);
const {EchoServiceClient} = require(genCodePath);
const {EchoRequest} = require(protoGenCodePath);
var echoService = new EchoServiceClient('MyHostname', null, null);
var request = new EchoRequest();
request.setMessage('aaa');
MockXMLHttpRequest.onSend = function(xhr) {
xhr.respond(200, {'Content-Type': 'application/grpc-web-text'},
// a trailer frame with content 'grpc-status:10'
'gAAAABBncnBjLXN0YXR1czoxMA0K');
};
var call = echoService.echo(request, {'custom-header-1':'value1'},
function(err, response) {
assert.equal(10, err.code);
done();
});
});
});
19 changes: 19 additions & 0 deletions scripts/docker-run-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#!/bin/bash
# Copyright 2018 Google LLC
#
# 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
#
# https://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.
set -ex

cd /github/grpc-web/packages/grpc-web && \
npm run prepare && \
npm test
4 changes: 4 additions & 0 deletions scripts/kokoro.sh
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,7 @@ source ./scripts/test-proxy.sh

# Remove all docker containers
docker-compose down

# Run unit tests from npm package
docker run grpc-web:prereqs /bin/bash \
/github/grpc-web/scripts/docker-run-tests.sh