call_test.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. *
  3. * Copyright 2015 gRPC authors.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. 'use strict';
  19. var assert = require('assert');
  20. var grpc = require('../src/grpc_extension');
  21. var constants = require('../src/constants');
  22. /**
  23. * Helper function to return an absolute deadline given a relative timeout in
  24. * seconds.
  25. * @param {number} timeout_secs The number of seconds to wait before timing out
  26. * @return {Date} A date timeout_secs in the future
  27. */
  28. function getDeadline(timeout_secs) {
  29. var deadline = new Date();
  30. deadline.setSeconds(deadline.getSeconds() + timeout_secs);
  31. return deadline;
  32. }
  33. var insecureCreds = grpc.ChannelCredentials.createInsecure();
  34. describe('call', function() {
  35. var channel;
  36. var server;
  37. before(function() {
  38. server = new grpc.Server();
  39. var port = server.addHttp2Port('localhost:0',
  40. grpc.ServerCredentials.createInsecure());
  41. server.start();
  42. channel = new grpc.Channel('localhost:' + port, insecureCreds);
  43. });
  44. after(function() {
  45. server.forceShutdown();
  46. });
  47. describe('constructor', function() {
  48. it('should reject anything less than 3 arguments', function() {
  49. assert.throws(function() {
  50. new grpc.Call();
  51. }, TypeError);
  52. assert.throws(function() {
  53. new grpc.Call(channel);
  54. }, TypeError);
  55. assert.throws(function() {
  56. new grpc.Call(channel, 'method');
  57. }, TypeError);
  58. });
  59. it('should succeed with a Channel, a string, and a date or number',
  60. function() {
  61. assert.doesNotThrow(function() {
  62. new grpc.Call(channel, 'method', new Date());
  63. });
  64. assert.doesNotThrow(function() {
  65. new grpc.Call(channel, 'method', 0);
  66. });
  67. });
  68. it('should accept an optional fourth string parameter', function() {
  69. assert.doesNotThrow(function() {
  70. new grpc.Call(channel, 'method', new Date(), 'host_override');
  71. });
  72. });
  73. it('should fail with a closed channel', function() {
  74. var local_channel = new grpc.Channel('hostname', insecureCreds);
  75. local_channel.close();
  76. assert.throws(function() {
  77. new grpc.Call(channel, 'method');
  78. });
  79. });
  80. it('should fail with other types', function() {
  81. assert.throws(function() {
  82. new grpc.Call({}, 'method', 0);
  83. }, TypeError);
  84. assert.throws(function() {
  85. new grpc.Call(channel, null, 0);
  86. }, TypeError);
  87. assert.throws(function() {
  88. new grpc.Call(channel, 'method', 'now');
  89. }, TypeError);
  90. });
  91. it('should succeed without the new keyword', function() {
  92. assert.doesNotThrow(function() {
  93. var call = grpc.Call(channel, 'method', new Date());
  94. assert(call instanceof grpc.Call);
  95. });
  96. });
  97. });
  98. describe('deadline', function() {
  99. it('should time out immediately with negative deadline', function(done) {
  100. var call = new grpc.Call(channel, 'method', -Infinity);
  101. var batch = {};
  102. batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
  103. call.startBatch(batch, function(err, response) {
  104. assert.strictEqual(response.status.code,
  105. constants.status.DEADLINE_EXCEEDED);
  106. done();
  107. });
  108. });
  109. });
  110. describe('startBatch', function() {
  111. it('should fail without an object and a function', function() {
  112. var call = new grpc.Call(channel, 'method', getDeadline(1));
  113. assert.throws(function() {
  114. call.startBatch();
  115. });
  116. assert.throws(function() {
  117. call.startBatch({});
  118. });
  119. assert.throws(function() {
  120. call.startBatch(null, function(){});
  121. });
  122. });
  123. it('should succeed with an empty object', function(done) {
  124. var call = new grpc.Call(channel, 'method', getDeadline(1));
  125. assert.doesNotThrow(function() {
  126. call.startBatch({}, function(err) {
  127. assert.ifError(err);
  128. done();
  129. });
  130. });
  131. });
  132. });
  133. describe('startBatch with metadata', function() {
  134. it('should succeed with a map of strings to string arrays', function(done) {
  135. var call = new grpc.Call(channel, 'method', getDeadline(1));
  136. assert.doesNotThrow(function() {
  137. var batch = {};
  138. batch[grpc.opType.SEND_INITIAL_METADATA] = {'key1': ['value1'],
  139. 'key2': ['value2']};
  140. call.startBatch(batch, function(err, resp) {
  141. assert.ifError(err);
  142. assert.deepEqual(resp, {'send_metadata': true});
  143. done();
  144. });
  145. });
  146. });
  147. it('should succeed with a map of strings to buffer arrays', function(done) {
  148. var call = new grpc.Call(channel, 'method', getDeadline(1));
  149. assert.doesNotThrow(function() {
  150. var batch = {};
  151. batch[grpc.opType.SEND_INITIAL_METADATA] = {
  152. 'key1-bin': [new Buffer('value1')],
  153. 'key2-bin': [new Buffer('value2')]
  154. };
  155. call.startBatch(batch, function(err, resp) {
  156. assert.ifError(err);
  157. assert.deepEqual(resp, {'send_metadata': true});
  158. done();
  159. });
  160. });
  161. });
  162. it('should fail with other parameter types', function() {
  163. var call = new grpc.Call(channel, 'method', getDeadline(1));
  164. assert.throws(function() {
  165. var batch = {};
  166. batch[grpc.opType.SEND_INITIAL_METADATA] = undefined;
  167. call.startBatch(batch, function(){});
  168. });
  169. assert.throws(function() {
  170. var batch = {};
  171. batch[grpc.opType.SEND_INITIAL_METADATA] = null;
  172. call.startBatch(batch, function(){});
  173. }, TypeError);
  174. assert.throws(function() {
  175. var batch = {};
  176. batch[grpc.opType.SEND_INITIAL_METADATA] = 'value';
  177. call.startBatch(batch, function(){});
  178. }, TypeError);
  179. assert.throws(function() {
  180. var batch = {};
  181. batch[grpc.opType.SEND_INITIAL_METADATA] = 5;
  182. call.startBatch(batch, function(){});
  183. }, TypeError);
  184. });
  185. });
  186. describe('startBatch with message', function() {
  187. it('should fail with null argument', function() {
  188. var call = new grpc.Call(channel, 'method', getDeadline(1));
  189. assert.throws(function() {
  190. var batch = {};
  191. batch[grpc.opType.SEND_MESSAGE] = null;
  192. call.startBatch(batch, function(){});
  193. }, TypeError);
  194. });
  195. it('should fail with numeric argument', function() {
  196. var call = new grpc.Call(channel, 'method', getDeadline(1));
  197. assert.throws(function() {
  198. var batch = {};
  199. batch[grpc.opType.SEND_MESSAGE] = 5;
  200. call.startBatch(batch, function(){});
  201. }, TypeError);
  202. });
  203. it('should fail with string argument', function() {
  204. var call = new grpc.Call(channel, 'method', getDeadline(1));
  205. assert.throws(function() {
  206. var batch = {};
  207. batch[grpc.opType.SEND_MESSAGE] = 'value';
  208. call.startBatch(batch, function(){});
  209. }, TypeError);
  210. });
  211. });
  212. describe('startBatch with status', function() {
  213. it('should fail without a code', function() {
  214. var call = new grpc.Call(channel, 'method', getDeadline(1));
  215. assert.throws(function() {
  216. var batch = {};
  217. batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
  218. details: 'details string',
  219. metadata: {}
  220. };
  221. call.startBatch(batch, function(){});
  222. }, TypeError);
  223. });
  224. it('should fail without details', function() {
  225. var call = new grpc.Call(channel, 'method', getDeadline(1));
  226. assert.throws(function() {
  227. var batch = {};
  228. batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
  229. code: 0,
  230. metadata: {}
  231. };
  232. call.startBatch(batch, function(){});
  233. }, TypeError);
  234. });
  235. it('should fail without metadata', function() {
  236. var call = new grpc.Call(channel, 'method', getDeadline(1));
  237. assert.throws(function() {
  238. var batch = {};
  239. batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
  240. code: 0,
  241. details: 'details string'
  242. };
  243. call.startBatch(batch, function(){});
  244. }, TypeError);
  245. });
  246. it('should fail with incorrectly typed code argument', function() {
  247. var call = new grpc.Call(channel, 'method', getDeadline(1));
  248. assert.throws(function() {
  249. var batch = {};
  250. batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
  251. code: 'code string',
  252. details: 'details string',
  253. metadata: {}
  254. };
  255. call.startBatch(batch, function(){});
  256. }, TypeError);
  257. });
  258. it('should fail with incorrectly typed details argument', function() {
  259. var call = new grpc.Call(channel, 'method', getDeadline(1));
  260. assert.throws(function() {
  261. var batch = {};
  262. batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
  263. code: 0,
  264. details: 5,
  265. metadata: {}
  266. };
  267. call.startBatch(batch, function(){});
  268. }, TypeError);
  269. });
  270. it('should fail with incorrectly typed metadata argument', function() {
  271. var call = new grpc.Call(channel, 'method', getDeadline(1));
  272. assert.throws(function() {
  273. var batch = {};
  274. batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
  275. code: 0,
  276. details: 'details string',
  277. metadata: 'abc'
  278. };
  279. call.startBatch(batch, function(){});
  280. }, TypeError);
  281. });
  282. });
  283. describe('cancel', function() {
  284. it('should succeed', function() {
  285. var call = new grpc.Call(channel, 'method', getDeadline(1));
  286. assert.doesNotThrow(function() {
  287. call.cancel();
  288. });
  289. });
  290. });
  291. describe('cancelWithStatus', function() {
  292. it('should reject anything other than an integer and a string', function() {
  293. assert.doesNotThrow(function() {
  294. var call = new grpc.Call(channel, 'method', getDeadline(1));
  295. call.cancelWithStatus(1, 'details');
  296. });
  297. assert.throws(function() {
  298. var call = new grpc.Call(channel, 'method', getDeadline(1));
  299. call.cancelWithStatus();
  300. });
  301. assert.throws(function() {
  302. var call = new grpc.Call(channel, 'method', getDeadline(1));
  303. call.cancelWithStatus('');
  304. });
  305. assert.throws(function() {
  306. var call = new grpc.Call(channel, 'method', getDeadline(1));
  307. call.cancelWithStatus(5, {});
  308. });
  309. });
  310. it('should reject the OK status code', function() {
  311. assert.throws(function() {
  312. var call = new grpc.Call(channel, 'method', getDeadline(1));
  313. call.cancelWithStatus(0, 'details');
  314. });
  315. });
  316. it('should result in the call ending with a status', function(done) {
  317. var call = new grpc.Call(channel, 'method', getDeadline(1));
  318. var batch = {};
  319. batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
  320. call.startBatch(batch, function(err, response) {
  321. assert.strictEqual(response.status.code, 5);
  322. assert.strictEqual(response.status.details, 'details');
  323. done();
  324. });
  325. call.cancelWithStatus(5, 'details');
  326. });
  327. });
  328. describe('getPeer', function() {
  329. it('should return a string', function() {
  330. var call = new grpc.Call(channel, 'method', getDeadline(1));
  331. assert.strictEqual(typeof call.getPeer(), 'string');
  332. });
  333. });
  334. });