1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
|
var assert = require('assert');
var client = require('../surface_client.js');
var ProtoBuf = require('protobufjs');
var port_picker = require('../port_picker');
var builder = ProtoBuf.loadProtoFile(__dirname + '/../examples/math.proto');
var math = builder.build('math');
/**
* Get a function that deserializes a specific type of protobuf.
* @param {function()} cls The constructor of the message type to deserialize
* @return {function(Buffer):cls} The deserialization function
*/
function deserializeCls(cls) {
/**
* Deserialize a buffer to a message object
* @param {Buffer} arg_buf The buffer to deserialize
* @return {cls} The resulting object
*/
return function deserialize(arg_buf) {
return cls.decode(arg_buf);
};
}
/**
* Serialize an object to a buffer
* @param {*} arg The object to serialize
* @return {Buffer} The serialized object
*/
function serialize(arg) {
return new Buffer(arg.encode().toBuffer());
}
/**
* Sends a Div request on the channel.
* @param {client.Channel} channel The channel on which to make the request
* @param {DivArg} argument The argument to the call. Should be serializable
* with serialize
* @param {function(?Error, value=)} The callback to for when the response is
* received
* @param {array=} Array of metadata key/value pairs to add to the call
* @param {(number|Date)=} deadline The deadline for processing this request.
* Defaults to infinite future
* @return {EventEmitter} An event emitter for stream related events
*/
var div = client.makeUnaryRequestFunction(
'/Math/Div',
serialize,
deserializeCls(math.DivReply));
/**
* Sends a Fib request on the channel.
* @param {client.Channel} channel The channel on which to make the request
* @param {*} argument The argument to the call. Should be serializable with
* serialize
* @param {array=} Array of metadata key/value pairs to add to the call
* @param {(number|Date)=} deadline The deadline for processing this request.
* Defaults to infinite future
* @return {EventEmitter} An event emitter for stream related events
*/
var fib = client.makeServerStreamRequestFunction(
'/Math/Fib',
serialize,
deserializeCls(math.Num));
/**
* Sends a Sum request on the channel.
* @param {client.Channel} channel The channel on which to make the request
* @param {function(?Error, value=)} The callback to for when the response is
* received
* @param {array=} Array of metadata key/value pairs to add to the call
* @param {(number|Date)=} deadline The deadline for processing this request.
* Defaults to infinite future
* @return {EventEmitter} An event emitter for stream related events
*/
var sum = client.makeClientStreamRequestFunction(
'/Math/Sum',
serialize,
deserializeCls(math.Num));
/**
* Sends a DivMany request on the channel.
* @param {client.Channel} channel The channel on which to make the request
* @param {array=} Array of metadata key/value pairs to add to the call
* @param {(number|Date)=} deadline The deadline for processing this request.
* Defaults to infinite future
* @return {EventEmitter} An event emitter for stream related events
*/
var divMany = client.makeBidiStreamRequestFunction(
'/Math/DivMany',
serialize,
deserializeCls(math.DivReply));
/**
* Channel to use to make requests to a running server.
*/
var channel;
/**
* Server to test against
*/
var server = require('../examples/math_server.js');
describe('Math client', function() {
before(function(done) {
port_picker.nextAvailablePort(function(port) {
server.bind(port).listen();
channel = new client.Channel(port);
done();
});
});
after(function() {
server.shutdown();
});
it('should handle a single request', function(done) {
var arg = new math.DivArgs({dividend: 7, divisor: 4});
var call = div(channel, arg, function handleDivResult(err, value) {
assert.ifError(err);
assert.equal(value.get('quotient'), 1);
assert.equal(value.get('remainder'), 3);
});
call.on('status', function checkStatus(status) {
assert.strictEqual(status.code, client.status.OK);
done();
});
});
it('should handle a server streaming request', function(done) {
var arg = new math.FibArgs({limit: 7});
var call = fib(channel, arg);
var expected_results = [1, 1, 2, 3, 5, 8, 13];
var next_expected = 0;
call.on('data', function checkResponse(value) {
assert.equal(value.get('num'), expected_results[next_expected]);
next_expected += 1;
});
call.on('status', function checkStatus(status) {
assert.strictEqual(status.code, client.status.OK);
done();
});
});
it('should handle a client streaming request', function(done) {
var call = sum(channel, function handleSumResult(err, value) {
assert.ifError(err);
assert.equal(value.get('num'), 21);
});
for (var i = 0; i < 7; i++) {
call.write(new math.Num({'num': i}));
}
call.end();
call.on('status', function checkStatus(status) {
assert.strictEqual(status.code, client.status.OK);
done();
});
});
it('should handle a bidirectional streaming request', function(done) {
function checkResponse(index, value) {
assert.equal(value.get('quotient'), index);
assert.equal(value.get('remainder'), 1);
}
var call = divMany(channel);
var response_index = 0;
call.on('data', function(value) {
checkResponse(response_index, value);
response_index += 1;
});
for (var i = 0; i < 7; i++) {
call.write(new math.DivArgs({dividend: 2 * i + 1, divisor: 2}));
}
call.end();
call.on('status', function checkStatus(status) {
assert.strictEqual(status.code, client.status.OK);
done();
});
});
});
|