From e6d5aaaab2ac20ad0efb37740436602effd68104 Mon Sep 17 00:00:00 2001 From: Stanley Cheung Date: Fri, 5 Jun 2020 21:44:51 -0700 Subject: [PATCH] Fix code generator bug and add tests --- javascript/net/grpc/web/grpc_generator.cc | 8 +- packages/grpc-web/package.json | 4 +- packages/grpc-web/test/protos/test01.proto | 9 ++ packages/grpc-web/test/protos/test02.proto | 6 + packages/grpc-web/test/protos/test03.proto | 4 + packages/grpc-web/test/tsc-tests/client01.ts | 10 ++ packages/grpc-web/test/tsc-tests/client02.ts | 10 ++ packages/grpc-web/test/tsc_test.js | 122 +++++++++++++++++++ 8 files changed, 169 insertions(+), 4 deletions(-) create mode 100644 packages/grpc-web/test/protos/test01.proto create mode 100644 packages/grpc-web/test/protos/test02.proto create mode 100644 packages/grpc-web/test/protos/test03.proto create mode 100644 packages/grpc-web/test/tsc-tests/client01.ts create mode 100644 packages/grpc-web/test/tsc-tests/client02.ts create mode 100644 packages/grpc-web/test/tsc_test.js diff --git a/javascript/net/grpc/web/grpc_generator.cc b/javascript/net/grpc/web/grpc_generator.cc index 09da8825..69085124 100644 --- a/javascript/net/grpc/web/grpc_generator.cc +++ b/javascript/net/grpc/web/grpc_generator.cc @@ -318,8 +318,12 @@ string JSMessageType(const Descriptor *desc, const FileDescriptor *file) { if (desc->file() != file) { module_prefix = ModuleAlias(desc->file()->name()) + "."; } - - return module_prefix + desc->name(); + string class_name; + class_name = StripPrefixString(desc->full_name(), desc->file()->package()); + if (!class_name.empty() && class_name[0] == '.') { + class_name = class_name.substr(1); + } + return module_prefix + class_name; } string JSElementType(const FieldDescriptor *desc, const FileDescriptor *file) diff --git a/packages/grpc-web/package.json b/packages/grpc-web/package.json index 180502d6..6a86b171 100644 --- a/packages/grpc-web/package.json +++ b/packages/grpc-web/package.json @@ -19,13 +19,13 @@ "build": "node scripts/build.js", "prepare": "npm run build && require-self", "prepublishOnly": "npm run build", - "test": "mocha --timeout 8000 \"./test/**/*_test.js\"" + "test": "mocha --timeout 60000 \"./test/**/*_test.js\"" }, "license": "Apache-2.0", "devDependencies": { "command-exists": "~1.2.8", "google-closure-compiler": "~20200224.0.0", - "google-protobuf": "~3.11.4", + "google-protobuf": "~3.12.0", "gulp": "~4.0.2", "gulp-eval": "~1.0.0", "mocha": "~5.2.0", diff --git a/packages/grpc-web/test/protos/test01.proto b/packages/grpc-web/test/protos/test01.proto new file mode 100644 index 00000000..96c711a9 --- /dev/null +++ b/packages/grpc-web/test/protos/test01.proto @@ -0,0 +1,9 @@ +syntax = "proto3"; + +message MessageOuter { + message MessageInner { + int32 value = 1; + } + + repeated MessageInner someProp = 1; +} diff --git a/packages/grpc-web/test/protos/test02.proto b/packages/grpc-web/test/protos/test02.proto new file mode 100644 index 00000000..d1c1095e --- /dev/null +++ b/packages/grpc-web/test/protos/test02.proto @@ -0,0 +1,6 @@ +syntax = "proto3"; +import "test03.proto"; + +service MyService { + rpc addOne(Integer) returns (Integer); +} diff --git a/packages/grpc-web/test/protos/test03.proto b/packages/grpc-web/test/protos/test03.proto new file mode 100644 index 00000000..b9b801cd --- /dev/null +++ b/packages/grpc-web/test/protos/test03.proto @@ -0,0 +1,4 @@ +syntax = "proto3"; + +message Integer { +} diff --git a/packages/grpc-web/test/tsc-tests/client01.ts b/packages/grpc-web/test/tsc-tests/client01.ts new file mode 100644 index 00000000..45d75de6 --- /dev/null +++ b/packages/grpc-web/test/tsc-tests/client01.ts @@ -0,0 +1,10 @@ +import * as grpcWeb from 'grpc-web'; + +import {MessageOuter} from './generated/test01_pb'; + +let inner1 = new MessageOuter.MessageInner(); +inner1.setValue(123); +let msgOuter = new MessageOuter(); +msgOuter.setSomepropList([inner1]); + +export {msgOuter} diff --git a/packages/grpc-web/test/tsc-tests/client02.ts b/packages/grpc-web/test/tsc-tests/client02.ts new file mode 100644 index 00000000..9facf624 --- /dev/null +++ b/packages/grpc-web/test/tsc-tests/client02.ts @@ -0,0 +1,10 @@ +import * as grpcWeb from 'grpc-web'; + +import {Integer} from './generated/test03_pb'; +import {MyServiceClient} from './generated/Test02ServiceClientPb'; + +const service = new MyServiceClient('http://mydummy.com', null, null); +const req = new Integer(); + +service.addOne(req, {}, (err: grpcWeb.Error, resp: Integer) => { +}); diff --git a/packages/grpc-web/test/tsc_test.js b/packages/grpc-web/test/tsc_test.js new file mode 100644 index 00000000..3960f247 --- /dev/null +++ b/packages/grpc-web/test/tsc_test.js @@ -0,0 +1,122 @@ +/** + * + * 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. + * + */ + +const assert = require('assert'); +const execSync = require('child_process').execSync; +const fs = require('fs'); +const path = require('path'); +const removeDirectory = require('./common.js').removeDirectory; +const mockXmlHttpRequest = require('mock-xmlhttprequest'); + +var MockXMLHttpRequest; + +function relativePath(relPath) { + return path.resolve(__dirname, relPath); +} +function cleanup() { + removeDirectory(relativePath('./tsc-tests/dist')); + removeDirectory(relativePath('./tsc-tests/generated')); +} +function createGeneratedCodeDir() { + fs.mkdirSync(relativePath('./tsc-tests/generated')); +} +function assertFileExists(relPath) { + assert.equal(true, fs.existsSync(relativePath(relPath))); +} +const outputDir = './test/tsc-tests/generated'; + +describe('tsc test01: nested messages', function() { + before(function() { + cleanup(); + createGeneratedCodeDir(); + execSync(`protoc -I=./test/protos test01.proto \ + --js_out=import_style=commonjs:${outputDir} \ + --grpc-web_out=import_style=commonjs+dts,mode=grpcwebtext:${outputDir}`); + }); + + after(function() { + cleanup(); + }); + + it('generated code should exist', function() { + assertFileExists('./tsc-tests/generated/test01_pb.js'); + assertFileExists('./tsc-tests/generated/test01_pb.d.ts'); + }); + + it('tsc should run and export', function() { + execSync(`tsc client01.ts generated/test01_pb.d.ts generated/test01_pb.js \ + --allowJs --outDir ./dist`, { + cwd: relativePath('./tsc-tests') + }); + + // check for the tsc output + assertFileExists('./tsc-tests/dist/client01.js'); + assertFileExists('./tsc-tests/dist/generated/test01_pb.js'); + + // load the compiled js files and do some tests + const {msgOuter} = require(relativePath('./tsc-tests/dist/client01.js')); + assert.equal(123, msgOuter.getSomepropList()[0].getValue()); + }); +}); + +describe('tsc test02: simple rpc, messages in separate proto', function() { + before(function() { + cleanup(); + createGeneratedCodeDir(); + MockXMLHttpRequest = mockXmlHttpRequest.newMockXhr(); + global.XMLHttpRequest = MockXMLHttpRequest; + execSync(`protoc -I=./test/protos test02.proto test03.proto \ + --js_out=import_style=commonjs:${outputDir} \ + --grpc-web_out=import_style=typescript,mode=grpcwebtext:${outputDir}`); + }); + + after(function() { + cleanup(); + }); + + it('generated code should exist', function() { + assertFileExists('./tsc-tests/generated/Test02ServiceClientPb.ts'); + assertFileExists('./tsc-tests/generated/test02_pb.js'); + assertFileExists('./tsc-tests/generated/test02_pb.d.ts'); + assertFileExists('./tsc-tests/generated/test03_pb.js'); + assertFileExists('./tsc-tests/generated/test03_pb.d.ts'); + }); + + it('tsc should run and export', function(done) { + execSync(`tsc client02.ts generated/Test02ServiceClientPb.ts \ + generated/test02_pb.d.ts generated/test02_pb.js \ + generated/test03_pb.d.ts generated/test03_pb.js \ + --allowJs --outDir ./dist`, { + cwd: relativePath('./tsc-tests') + }); + + // check for the tsc output + assertFileExists('./tsc-tests/dist/client02.js'); + assertFileExists('./tsc-tests/dist/generated/Test02ServiceClientPb.js'); + assertFileExists('./tsc-tests/dist/generated/test02_pb.js'); + assertFileExists('./tsc-tests/dist/generated/test03_pb.js'); + + // load the compiled js files and do some tests + MockXMLHttpRequest.onSend = function(xhr) { + assert.equal('http://mydummy.com/MyService/addOne', xhr.url); + assert.equal('AAAAAAA=', xhr.body); + done(); + }; + require(relativePath('./tsc-tests/dist/client02.js')); + }); +});