1import { ThriftTest } from "./gen-js/ThriftTest_types";
2import "./gen-js/ThriftTest";
3
4var Int64 = require("node-int64");
5var JSONInt64 = require("json-int64");
6var QUnit = require("./qunit");
7
8const transport: Thrift.Transport = new Thrift.Transport("/service");
9const protocol: Thrift.Protocol = new Thrift.Protocol(transport);
10const client: ThriftTest.ThriftTestClient = new ThriftTest.ThriftTestClient(protocol);
11
12const int64_2_pow_60: typeof Int64 = new Int64('1000000000000000');
13const int64_minus_2_pow_60: typeof Int64 = new Int64('f000000000000000');
14
15// Work around for old API used by QUnitAdapter of jsTestDriver
16if (typeof QUnit.log == 'function') {
17    // When using real QUnit (fron PhantomJS) log failures to console
18    QUnit.log(function(details) {
19        if (!details.result) {
20        console.log('======== FAIL ========');
21        console.log('TestName: ' + details.name);
22        if (details.message) console.log(details.message);
23        console.log('Expected: ' + JSONInt64.stringify(details.expected));
24        console.log('Actual  : ' + JSONInt64.stringify(details.actual));
25        console.log('======================');
26        }
27    });
28}
29
30// all Languages in UTF-8
31const stringTest: string = "Afrikaans, Alemannisch, Aragonés, العربية, مصرى, Asturianu, Aymar aru, Azərbaycan, Башҡорт, Boarisch, Žemaitėška, Беларуская, Беларуская (тарашкевіца), Български, Bamanankan, বাংলা, Brezhoneg, Bosanski, Català, Mìng-dĕ̤ng-ngṳ̄, Нохчийн, Cebuano, ᏣᎳᎩ, Česky, Словѣ́ньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ, Чӑвашла, Cymraeg, Dansk, Zazaki, ދިވެހިބަސް, Ελληνικά, Emiliàn e rumagnòl, English, Esperanto, Español, Eesti, Euskara, فارسی, Suomi, Võro, Føroyskt, Français, Arpetan, Furlan, Frysk, Gaeilge, 贛語, Gàidhlig, Galego, Avañe'ẽ, ગુજરાતી, Gaelg, עברית, हिन्दी, Fiji Hindi, Hrvatski, Kreyòl ayisyen, Magyar, Հայերեն, Interlingua, Bahasa Indonesia, Ilokano, Ido, Íslenska, Italiano, 日本語, Lojban, Basa Jawa, ქართული, Kongo, Kalaallisut, ಕನ್ನಡ, 한국어, Къарачай-Малкъар, Ripoarisch, Kurdî, Коми, Kernewek, Кыргызча, Latina, Ladino, Lëtzebuergesch, Limburgs, Lingála, ລາວ, Lietuvių, Latviešu, Basa Banyumasan, Malagasy, Македонски, മലയാളം, मराठी, Bahasa Melayu, مازِرونی, Nnapulitano, Nedersaksisch, नेपाल भाषा, Nederlands, ‪Norsk (nynorsk)‬, ‪Norsk (bokmål)‬, Nouormand, Diné bizaad, Occitan, Иронау, Papiamentu, Deitsch, Norfuk / Pitkern, Polski, پنجابی, پښتو, Português, Runa Simi, Rumantsch, Romani, Română, Русский, Саха тыла, Sardu, Sicilianu, Scots, Sámegiella, Simple English, Slovenčina, Slovenščina, Српски / Srpski, Seeltersk, Svenska, Kiswahili, தமிழ், తెలుగు, Тоҷикӣ, ไทย, Türkmençe, Tagalog, Türkçe, Татарча/Tatarça, Українська, اردو, Tiếng Việt, Volapük, Walon, Winaray, 吴语, isiXhosa, ייִדיש, Yorùbá, Zeêuws, 中文, Bân-lâm-gú, 粵語";
32
33
34function checkRecursively(assert, map1: Object, map2: Object): void {
35    if (typeof map1 !== 'function' && typeof map2 !== 'function') {
36        if (!map1 || typeof map1 !== 'object') {
37            assert.equal(map1, map2);
38        } else {
39            for (let key in map1) {
40            checkRecursively(assert, map1[key], map2[key]);
41            }
42        }
43    }
44}
45
46
47QUnit.module('Base Types');
48
49    QUnit.test('Void', function(assert) {
50        assert.equal(client.testVoid(), undefined);
51    });
52    QUnit.test('Binary (String)', function(assert) {
53        let binary: string = '';
54        for (let v = 255; v >= 0; --v) {
55            binary += String.fromCharCode(v);
56        }
57        assert.equal(client.testBinary(binary), binary);
58    });
59    QUnit.test('Binary (Uint8Array)', function(assert) {
60        let binary: string = '';
61        for (let v = 255; v >= 0; --v) {
62            binary += String.fromCharCode(v);
63        }
64        const arr: Uint8Array = new Uint8Array(binary.length);
65        for (let i = 0; i < binary.length; ++i) {
66            arr[i] = binary[i].charCodeAt(0);
67        }
68        const hexEncodedString = Array.from(arr, function(byte) {
69            return String.fromCharCode(byte);
70        }).join('')
71        assert.equal(client.testBinary(hexEncodedString), binary);
72    });
73    QUnit.test('String', function(assert) {
74        assert.equal(client.testString(''), '');
75        assert.equal(client.testString(stringTest), stringTest);
76
77        const specialCharacters: string = 'quote: \" backslash:' +
78            ' forwardslash-escaped: \/ ' +
79            ' backspace: \b formfeed: \f newline: \n return: \r tab: ' +
80            ' now-all-of-them-together: "\\\/\b\n\r\t' +
81            ' now-a-bunch-of-junk: !@#$%&()(&%$#{}{}<><><';
82        assert.equal(client.testString(specialCharacters), specialCharacters);
83    });
84    QUnit.test('Double', function(assert) {
85        assert.equal(client.testDouble(0), 0);
86        assert.equal(client.testDouble(-1), -1);
87        assert.equal(client.testDouble(3.14), 3.14);
88        assert.equal(client.testDouble(Math.pow(2, 60)), Math.pow(2, 60));
89    });
90    QUnit.test('Byte', function(assert) {
91        assert.equal(client.testByte(0), 0);
92        assert.equal(client.testByte(0x01), 0x01);
93    });
94    QUnit.test('I32', function(assert) {
95        assert.equal(client.testI32(0), 0);
96        assert.equal(client.testI32(Math.pow(2, 30)), Math.pow(2, 30));
97        assert.equal(client.testI32(-Math.pow(2, 30)), -Math.pow(2, 30));
98    });
99    QUnit.test('I64', function(assert) {
100        assert.equal(client.testI64(new Int64(0)), 0);
101
102        let int64_2_pow_60_result: typeof Int64 = client.testI64(int64_2_pow_60);
103        assert.ok(int64_2_pow_60.equals(int64_2_pow_60_result));
104
105        let int64_minus_2_pow_60_result: typeof Int64 = client.testI64(int64_minus_2_pow_60);
106        assert.ok(int64_minus_2_pow_60.equals(int64_minus_2_pow_60_result));
107    });
108
109
110QUnit.module('Structured Types');
111
112    QUnit.test('Struct', function(assert) {
113        const structTestInput: ThriftTest.Xtruct = new ThriftTest.Xtruct();
114        structTestInput.string_thing = 'worked';
115        structTestInput.byte_thing = 0x01;
116        structTestInput.i32_thing = Math.pow(2, 30);
117        structTestInput.i64_thing = int64_2_pow_60;
118
119        const structTestOutput: ThriftTest.Xtruct = client.testStruct(structTestInput);
120
121        assert.equal(structTestOutput.string_thing, structTestInput.string_thing);
122        assert.equal(structTestOutput.byte_thing, structTestInput.byte_thing);
123        assert.equal(structTestOutput.i32_thing, structTestInput.i32_thing);
124        assert.ok(structTestOutput.i64_thing.equals(structTestInput.i64_thing));
125        assert.ok(structTestInput.i64_thing.equals(structTestOutput.i64_thing));
126
127        assert.equal(JSONInt64.stringify(structTestOutput), JSONInt64.stringify(structTestInput));
128    });
129
130    QUnit.test('Nest', function(assert) {
131        const xtrTestInput: ThriftTest.Xtruct = new ThriftTest.Xtruct();
132        xtrTestInput.string_thing = 'worked';
133        xtrTestInput.byte_thing = 0x01;
134        xtrTestInput.i32_thing = Math.pow(2, 30);
135        xtrTestInput.i64_thing = int64_2_pow_60;
136
137        const nestTestInput: ThriftTest.Xtruct2 = new ThriftTest.Xtruct2();
138        nestTestInput.byte_thing = 0x02;
139        nestTestInput.struct_thing = xtrTestInput;
140        nestTestInput.i32_thing = Math.pow(2, 15);
141
142        const nestTestOutput: ThriftTest.Xtruct2 = client.testNest(nestTestInput);
143
144        assert.equal(nestTestOutput.byte_thing, nestTestInput.byte_thing);
145        assert.equal(nestTestOutput.struct_thing.string_thing, nestTestInput.struct_thing.string_thing);
146        assert.equal(nestTestOutput.struct_thing.byte_thing, nestTestInput.struct_thing.byte_thing);
147        assert.equal(nestTestOutput.struct_thing.i32_thing, nestTestInput.struct_thing.i32_thing);
148        assert.ok(nestTestOutput.struct_thing.i64_thing.equals(nestTestInput.struct_thing.i64_thing));
149        assert.equal(nestTestOutput.i32_thing, nestTestInput.i32_thing);
150
151        assert.equal(JSONInt64.stringify(nestTestOutput), JSONInt64.stringify(nestTestInput));
152    });
153
154    QUnit.test('Map', function(assert) {
155        const mapTestInput: {[k: number]: number;} = {7: 77, 8: 88, 9: 99};
156
157        const mapTestOutput: {[k: number]: number;} = client.testMap(mapTestInput);
158
159        for (let key in mapTestOutput) {
160            assert.equal(mapTestOutput[key], mapTestInput[key]);
161        }
162    });
163
164    QUnit.test('StringMap', function(assert) {
165        const mapTestInput: {[k: string]: string;} = {
166            'a': '123', 'a b': 'with spaces ', 'same': 'same', '0': 'numeric key',
167            'longValue': stringTest, stringTest: 'long key'
168        };
169
170        const mapTestOutput: {[k: string]: string;} = client.testStringMap(mapTestInput);
171
172        for (let key in mapTestOutput) {
173            assert.equal(mapTestOutput[key], mapTestInput[key]);
174        }
175    });
176
177    QUnit.test('Set', function(assert) {
178        const setTestInput: number[] = [1, 2, 3];
179        assert.ok(client.testSet(setTestInput), setTestInput);
180    });
181
182    QUnit.test('List', function(assert) {
183        const listTestInput: number[] = [1, 2, 3];
184        assert.ok(client.testList(listTestInput), listTestInput);
185    });
186
187    QUnit.test('Enum', function(assert) {
188        assert.equal(client.testEnum(ThriftTest.Numberz.ONE), ThriftTest.Numberz.ONE);
189    });
190
191    QUnit.test('TypeDef', function(assert) {
192        assert.equal(client.testTypedef(new Int64(69)), 69);
193    });
194
195
196QUnit.module('deeper!');
197
198    QUnit.test('MapMap', function(assert) {
199        const mapMapTestExpectedResult: {[K: number]: {[k: number]: number}} = {
200            '4': {'1': 1, '2': 2, '3': 3, '4': 4},
201            '-4': {'-4': -4, '-3': -3, '-2': -2, '-1': -1}
202        };
203
204        const mapMapTestOutput = client.testMapMap(1);
205
206
207        for (let key in mapMapTestOutput) {
208            for (let key2 in mapMapTestOutput[key]) {
209                assert.equal(mapMapTestOutput[key][key2], mapMapTestExpectedResult[key][key2]);
210            }
211        }
212
213        checkRecursively(assert, mapMapTestOutput, mapMapTestExpectedResult);
214    });
215
216
217QUnit.module('Exception');
218
219    QUnit.test('Xception', function(assert) {
220        assert.expect(2);
221        const done = assert.async();
222        try {
223            client.testException('Xception');
224            assert.ok(false);
225        }catch (e) {
226            assert.equal(e.errorCode, 1001);
227            assert.equal(e.message, 'Xception');
228            done();
229        }
230    });
231
232    QUnit.test('no Exception', function(assert) {
233        assert.expect(1);
234        try {
235            client.testException('no Exception');
236            assert.ok(true);
237        }catch (e) {
238            assert.ok(false);
239        }
240    });
241
242    QUnit.test('TException', function(assert) {
243        //ThriftTest does not list TException as a legal exception so it will
244        // generate an exception on the server that does not propagate back to
245        // the client. This test has been modified to equate to "no exception"
246        assert.expect(1);
247        try {
248            client.testException('TException');
249        } catch (e) {
250            //assert.ok(false);
251        }
252        assert.ok(true);
253    });
254
255
256QUnit.module('Insanity');
257
258    const crazy: ThriftTest.Insanity = {
259        'userMap': { '5': new Int64(5), '8': new Int64(8) },
260        'xtructs': [{
261            'string_thing': 'Goodbye4',
262            'byte_thing': 4,
263            'i32_thing': 4,
264            'i64_thing': new Int64(4)
265        },
266        {
267            'string_thing': 'Hello2',
268            'byte_thing': 2,
269            'i32_thing': 2,
270            'i64_thing': new Int64(2)
271        }]
272    };
273    QUnit.test('testInsanity', function(assert) {
274        const insanity: {[k: number]: (ThriftTest.Insanity | {[k:number]: ThriftTest.Insanity})} = {
275            '1': {
276                '2': crazy,
277                '3': crazy
278            },
279            '2': { '6': new ThriftTest.Insanity() }
280        };
281        const res = client.testInsanity(new ThriftTest.Insanity(crazy));
282        assert.ok(res, JSONInt64.stringify(res));
283        assert.ok(insanity, JSONInt64.stringify(insanity));
284
285        checkRecursively(assert, res, insanity);
286    });
287
288
289//////////////////////////////////
290//Run same tests asynchronously
291
292QUnit.module('Async');
293
294    QUnit.test('Double', function(assert) {
295        assert.expect(1);
296
297        const done = assert.async();
298        client.testDouble(3.14159265, function(result) {
299            assert.equal(result, 3.14159265);
300            done();
301        });
302    });
303
304    QUnit.test('Byte', function(assert) {
305        assert.expect(1);
306
307        const done = assert.async();
308        client.testByte(0x01, function(result) {
309            assert.equal(result, 0x01);
310            done();
311        });
312    });
313
314    QUnit.test('I32', function(assert) {
315        assert.expect(2);
316
317        const done = assert.async(2);
318        client.testI32(Math.pow(2, 30), function(result) {
319            assert.equal(result, Math.pow(2, 30));
320            done();
321        });
322
323        client.testI32(Math.pow(-2, 31), function(result) {
324            assert.equal(result, Math.pow(-2, 31));
325            done();
326        });
327    });
328
329    QUnit.test('I64', function(assert) {
330        assert.expect(2);
331
332        const done = assert.async(2);
333        client.testI64(int64_2_pow_60, function(result) {
334            assert.ok(int64_2_pow_60.equals(result));
335            done();
336        });
337
338        client.testI64(int64_minus_2_pow_60, function(result) {
339            assert.ok(int64_minus_2_pow_60.equals(result));
340            done();
341        });
342    });
343