1/* 2 * Licensed to the Apache Software Foundation (ASF) under one 3 * or more contributor license agreements. See the NOTICE file 4 * distributed with this work for additional information 5 * regarding copyright ownership. The ASF licenses this file 6 * to you under the Apache License, Version 2.0 (the 7 * "License"); you may not use this file except in compliance 8 * with the License. You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, 13 * software distributed under the License is distributed on an 14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 * KIND, either express or implied. See the License for the 16 * specific language governing permissions and limitations 17 * under the License. 18 */ 19 20const ttypes = require("./gen-nodejs/JsDeepConstructorTest_types"); 21const thrift = require("thrift"); 22const test = require("tape"); 23const bufferEquals = require("buffer-equals"); 24 25function serializeBinary(data) { 26 let buff; 27 const transport = new thrift.TBufferedTransport(null, function(msg) { 28 buff = msg; 29 }); 30 const prot = new thrift.TBinaryProtocol(transport); 31 data.write(prot); 32 prot.flush(); 33 return buff; 34} 35 36function deserializeBinary(serialized, type) { 37 const t = new thrift.TFramedTransport(serialized); 38 const p = new thrift.TBinaryProtocol(t); 39 const data = new type(); 40 data.read(p); 41 return data; 42} 43 44function serializeJSON(data) { 45 let buff; 46 const transport = new thrift.TBufferedTransport(null, function(msg) { 47 buff = msg; 48 }); 49 const protocol = new thrift.TJSONProtocol(transport); 50 protocol.writeMessageBegin("", 0, 0); 51 data.write(protocol); 52 protocol.writeMessageEnd(); 53 protocol.flush(); 54 return buff; 55} 56 57function deserializeJSON(serialized, type) { 58 const transport = new thrift.TFramedTransport(serialized); 59 const protocol = new thrift.TJSONProtocol(transport); 60 protocol.readMessageBegin(); 61 const data = new type(); 62 data.read(protocol); 63 protocol.readMessageEnd(); 64 return data; 65} 66 67function createThriftObj() { 68 return new ttypes.Complex({ 69 struct_field: new ttypes.Simple({ value: "a" }), 70 71 struct_list_field: [ 72 new ttypes.Simple({ value: "b" }), 73 new ttypes.Simple({ value: "c" }) 74 ], 75 76 struct_set_field: [ 77 new ttypes.Simple({ value: "d" }), 78 new ttypes.Simple({ value: "e" }) 79 ], 80 81 struct_map_field: { 82 A: new ttypes.Simple({ value: "f" }), 83 B: new ttypes.Simple({ value: "g" }) 84 }, 85 86 struct_nested_containers_field: [ 87 [ 88 { 89 C: [ 90 new ttypes.Simple({ value: "h" }), 91 new ttypes.Simple({ value: "i" }) 92 ] 93 } 94 ] 95 ], 96 97 struct_nested_containers_field2: { 98 D: [ 99 { 100 DA: new ttypes.Simple({ value: "j" }) 101 }, 102 { 103 DB: new ttypes.Simple({ value: "k" }) 104 } 105 ] 106 }, 107 108 list_of_list_field: [ 109 ["l00", "l01", "l02"], 110 ["l10", "l11", "l12"], 111 ["l20", "l21", "l22"] 112 ], 113 114 list_of_list_of_list_field: [ 115 [ 116 ["m000", "m001", "m002"], 117 ["m010", "m011", "m012"], 118 ["m020", "m021", "m022"] 119 ], 120 [ 121 ["m100", "m101", "m102"], 122 ["m110", "m111", "m112"], 123 ["m120", "m121", "m122"] 124 ], 125 [ 126 ["m200", "m201", "m202"], 127 ["m210", "m211", "m212"], 128 ["m220", "m221", "m222"] 129 ] 130 ] 131 }); 132} 133 134function createJsObj() { 135 return { 136 struct_field: { value: "a" }, 137 138 struct_list_field: [{ value: "b" }, { value: "c" }], 139 140 struct_set_field: [{ value: "d" }, { value: "e" }], 141 142 struct_map_field: { 143 A: { value: "f" }, 144 B: { value: "g" } 145 }, 146 147 struct_nested_containers_field: [ 148 [ 149 { 150 C: [{ value: "h" }, { value: "i" }] 151 } 152 ] 153 ], 154 155 struct_nested_containers_field2: { 156 D: [ 157 { 158 DA: { value: "j" } 159 }, 160 { 161 DB: { value: "k" } 162 } 163 ] 164 }, 165 166 list_of_list_field: [ 167 ["l00", "l01", "l02"], 168 ["l10", "l11", "l12"], 169 ["l20", "l21", "l22"] 170 ], 171 172 list_of_list_of_list_field: [ 173 [ 174 ["m000", "m001", "m002"], 175 ["m010", "m011", "m012"], 176 ["m020", "m021", "m022"] 177 ], 178 [ 179 ["m100", "m101", "m102"], 180 ["m110", "m111", "m112"], 181 ["m120", "m121", "m122"] 182 ], 183 [ 184 ["m200", "m201", "m202"], 185 ["m210", "m211", "m212"], 186 ["m220", "m221", "m222"] 187 ] 188 ] 189 }; 190} 191 192function assertValues(obj, assert) { 193 assert.equals(obj.struct_field.value, "a"); 194 assert.equals(obj.struct_list_field[0].value, "b"); 195 assert.equals(obj.struct_list_field[1].value, "c"); 196 assert.equals(obj.struct_set_field[0].value, "d"); 197 assert.equals(obj.struct_set_field[1].value, "e"); 198 assert.equals(obj.struct_map_field.A.value, "f"); 199 assert.equals(obj.struct_map_field.B.value, "g"); 200 assert.equals(obj.struct_nested_containers_field[0][0].C[0].value, "h"); 201 assert.equals(obj.struct_nested_containers_field[0][0].C[1].value, "i"); 202 assert.equals(obj.struct_nested_containers_field2.D[0].DA.value, "j"); 203 assert.equals(obj.struct_nested_containers_field2.D[1].DB.value, "k"); 204 assert.equals(obj.list_of_list_field[0][0], "l00"); 205 assert.equals(obj.list_of_list_field[0][1], "l01"); 206 assert.equals(obj.list_of_list_field[0][2], "l02"); 207 assert.equals(obj.list_of_list_field[1][0], "l10"); 208 assert.equals(obj.list_of_list_field[1][1], "l11"); 209 assert.equals(obj.list_of_list_field[1][2], "l12"); 210 assert.equals(obj.list_of_list_field[2][0], "l20"); 211 assert.equals(obj.list_of_list_field[2][1], "l21"); 212 assert.equals(obj.list_of_list_field[2][2], "l22"); 213 214 assert.equals(obj.list_of_list_of_list_field[0][0][0], "m000"); 215 assert.equals(obj.list_of_list_of_list_field[0][0][1], "m001"); 216 assert.equals(obj.list_of_list_of_list_field[0][0][2], "m002"); 217 assert.equals(obj.list_of_list_of_list_field[0][1][0], "m010"); 218 assert.equals(obj.list_of_list_of_list_field[0][1][1], "m011"); 219 assert.equals(obj.list_of_list_of_list_field[0][1][2], "m012"); 220 assert.equals(obj.list_of_list_of_list_field[0][2][0], "m020"); 221 assert.equals(obj.list_of_list_of_list_field[0][2][1], "m021"); 222 assert.equals(obj.list_of_list_of_list_field[0][2][2], "m022"); 223 224 assert.equals(obj.list_of_list_of_list_field[1][0][0], "m100"); 225 assert.equals(obj.list_of_list_of_list_field[1][0][1], "m101"); 226 assert.equals(obj.list_of_list_of_list_field[1][0][2], "m102"); 227 assert.equals(obj.list_of_list_of_list_field[1][1][0], "m110"); 228 assert.equals(obj.list_of_list_of_list_field[1][1][1], "m111"); 229 assert.equals(obj.list_of_list_of_list_field[1][1][2], "m112"); 230 assert.equals(obj.list_of_list_of_list_field[1][2][0], "m120"); 231 assert.equals(obj.list_of_list_of_list_field[1][2][1], "m121"); 232 assert.equals(obj.list_of_list_of_list_field[1][2][2], "m122"); 233 234 assert.equals(obj.list_of_list_of_list_field[2][0][0], "m200"); 235 assert.equals(obj.list_of_list_of_list_field[2][0][1], "m201"); 236 assert.equals(obj.list_of_list_of_list_field[2][0][2], "m202"); 237 assert.equals(obj.list_of_list_of_list_field[2][1][0], "m210"); 238 assert.equals(obj.list_of_list_of_list_field[2][1][1], "m211"); 239 assert.equals(obj.list_of_list_of_list_field[2][1][2], "m212"); 240 assert.equals(obj.list_of_list_of_list_field[2][2][0], "m220"); 241 assert.equals(obj.list_of_list_of_list_field[2][2][1], "m221"); 242 assert.equals(obj.list_of_list_of_list_field[2][2][2], "m222"); 243} 244 245function createTestCases(serialize, deserialize) { 246 const cases = { 247 "Serialize/deserialize should return equal object": function(assert) { 248 const tObj = createThriftObj(); 249 const received = deserialize(serialize(tObj), ttypes.Complex); 250 assert.ok(tObj !== received, "not the same object"); 251 assert.deepEqual(tObj, received); 252 assert.end(); 253 }, 254 255 "Nested structs and containers initialized from plain js objects should serialize same as if initialized from thrift objects": function( 256 assert 257 ) { 258 const tObj1 = createThriftObj(); 259 const tObj2 = new ttypes.Complex(createJsObj()); 260 assertValues(tObj2, assert); 261 const s1 = serialize(tObj1); 262 const s2 = serialize(tObj2); 263 assert.ok(bufferEquals(s1, s2)); 264 assert.end(); 265 }, 266 267 "Modifications to args object should not affect constructed Thrift object": function( 268 assert 269 ) { 270 const args = createJsObj(); 271 assertValues(args, assert); 272 273 const tObj = new ttypes.Complex(args); 274 assertValues(tObj, assert); 275 276 args.struct_field.value = "ZZZ"; 277 args.struct_list_field[0].value = "ZZZ"; 278 args.struct_list_field[1].value = "ZZZ"; 279 args.struct_set_field[0].value = "ZZZ"; 280 args.struct_set_field[1].value = "ZZZ"; 281 args.struct_map_field.A.value = "ZZZ"; 282 args.struct_map_field.B.value = "ZZZ"; 283 args.struct_nested_containers_field[0][0].C[0] = "ZZZ"; 284 args.struct_nested_containers_field[0][0].C[1] = "ZZZ"; 285 args.struct_nested_containers_field2.D[0].DA = "ZZZ"; 286 args.struct_nested_containers_field2.D[0].DB = "ZZZ"; 287 288 assertValues(tObj, assert); 289 assert.end(); 290 }, 291 292 "nulls are ok": function(assert) { 293 const tObj = new ttypes.Complex({ 294 struct_field: null, 295 struct_list_field: null, 296 struct_set_field: null, 297 struct_map_field: null, 298 struct_nested_containers_field: null, 299 struct_nested_containers_field2: null 300 }); 301 const received = deserialize(serialize(tObj), ttypes.Complex); 302 assert.strictEqual(tObj.struct_field, null); 303 assert.ok(tObj !== received); 304 assert.deepEqual(tObj, received); 305 assert.end(); 306 }, 307 308 "Can make list with objects": function(assert) { 309 const tObj = new ttypes.ComplexList({ 310 struct_list_field: [new ttypes.Complex({})] 311 }); 312 const innerObj = tObj.struct_list_field[0]; 313 assert.ok(innerObj instanceof ttypes.Complex); 314 assert.strictEqual(innerObj.struct_field, null); 315 assert.strictEqual(innerObj.struct_list_field, null); 316 assert.strictEqual(innerObj.struct_set_field, null); 317 assert.strictEqual(innerObj.struct_map_field, null); 318 assert.strictEqual(innerObj.struct_nested_containers_field, null); 319 assert.strictEqual(innerObj.struct_nested_containers_field2, null); 320 assert.end(); 321 } 322 }; 323 return cases; 324} 325 326function run(name, cases) { 327 Object.keys(cases).forEach(function(caseName) { 328 test(name + ": " + caseName, cases[caseName]); 329 }); 330} 331 332run("binary", createTestCases(serializeBinary, deserializeBinary)); 333run("json", createTestCases(serializeJSON, deserializeJSON)); 334