1*1b3f573fSAndroid Build Coastguard Worker#!/usr/bin/env node 2*1b3f573fSAndroid Build Coastguard Worker// Protocol Buffers - Google's data interchange format 3*1b3f573fSAndroid Build Coastguard Worker// Copyright 2008 Google Inc. All rights reserved. 4*1b3f573fSAndroid Build Coastguard Worker// https://developers.google.com/protocol-buffers/ 5*1b3f573fSAndroid Build Coastguard Worker// 6*1b3f573fSAndroid Build Coastguard Worker// Redistribution and use in source and binary forms, with or without 7*1b3f573fSAndroid Build Coastguard Worker// modification, are permitted provided that the following conditions are 8*1b3f573fSAndroid Build Coastguard Worker// met: 9*1b3f573fSAndroid Build Coastguard Worker// 10*1b3f573fSAndroid Build Coastguard Worker// * Redistributions of source code must retain the above copyright 11*1b3f573fSAndroid Build Coastguard Worker// notice, this list of conditions and the following disclaimer. 12*1b3f573fSAndroid Build Coastguard Worker// * Redistributions in binary form must reproduce the above 13*1b3f573fSAndroid Build Coastguard Worker// copyright notice, this list of conditions and the following disclaimer 14*1b3f573fSAndroid Build Coastguard Worker// in the documentation and/or other materials provided with the 15*1b3f573fSAndroid Build Coastguard Worker// distribution. 16*1b3f573fSAndroid Build Coastguard Worker// * Neither the name of Google Inc. nor the names of its 17*1b3f573fSAndroid Build Coastguard Worker// contributors may be used to endorse or promote products derived from 18*1b3f573fSAndroid Build Coastguard Worker// this software without specific prior written permission. 19*1b3f573fSAndroid Build Coastguard Worker// 20*1b3f573fSAndroid Build Coastguard Worker// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21*1b3f573fSAndroid Build Coastguard Worker// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*1b3f573fSAndroid Build Coastguard Worker// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23*1b3f573fSAndroid Build Coastguard Worker// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24*1b3f573fSAndroid Build Coastguard Worker// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25*1b3f573fSAndroid Build Coastguard Worker// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26*1b3f573fSAndroid Build Coastguard Worker// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27*1b3f573fSAndroid Build Coastguard Worker// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28*1b3f573fSAndroid Build Coastguard Worker// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29*1b3f573fSAndroid Build Coastguard Worker// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30*1b3f573fSAndroid Build Coastguard Worker// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31*1b3f573fSAndroid Build Coastguard Worker 32*1b3f573fSAndroid Build Coastguard Workervar conformance = require('conformance_pb'); 33*1b3f573fSAndroid Build Coastguard Workervar test_messages_proto3 = require('google/protobuf/test_messages_proto3_pb'); 34*1b3f573fSAndroid Build Coastguard Workervar test_messages_proto2 = require('google/protobuf/test_messages_proto2_pb'); 35*1b3f573fSAndroid Build Coastguard Workervar fs = require('fs'); 36*1b3f573fSAndroid Build Coastguard Worker 37*1b3f573fSAndroid Build Coastguard Workervar testCount = 0; 38*1b3f573fSAndroid Build Coastguard Worker 39*1b3f573fSAndroid Build Coastguard Workerfunction doTest(request) { 40*1b3f573fSAndroid Build Coastguard Worker var testMessage; 41*1b3f573fSAndroid Build Coastguard Worker var response = new conformance.ConformanceResponse(); 42*1b3f573fSAndroid Build Coastguard Worker 43*1b3f573fSAndroid Build Coastguard Worker try { 44*1b3f573fSAndroid Build Coastguard Worker if (request.getRequestedOutputFormat() == conformance.WireFormat.JSON) { 45*1b3f573fSAndroid Build Coastguard Worker response.setSkipped("JSON not supported."); 46*1b3f573fSAndroid Build Coastguard Worker return response; 47*1b3f573fSAndroid Build Coastguard Worker } 48*1b3f573fSAndroid Build Coastguard Worker 49*1b3f573fSAndroid Build Coastguard Worker if (request.getRequestedOutputFormat() == 50*1b3f573fSAndroid Build Coastguard Worker conformance.WireFormat.TEXT_FORMAT) { 51*1b3f573fSAndroid Build Coastguard Worker response.setSkipped('Text format is not supported as output format.'); 52*1b3f573fSAndroid Build Coastguard Worker return response; 53*1b3f573fSAndroid Build Coastguard Worker } 54*1b3f573fSAndroid Build Coastguard Worker 55*1b3f573fSAndroid Build Coastguard Worker switch (request.getPayloadCase()) { 56*1b3f573fSAndroid Build Coastguard Worker case conformance.ConformanceRequest.PayloadCase.PROTOBUF_PAYLOAD: { 57*1b3f573fSAndroid Build Coastguard Worker if (request.getMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3") { 58*1b3f573fSAndroid Build Coastguard Worker try { 59*1b3f573fSAndroid Build Coastguard Worker testMessage = test_messages_proto3.TestAllTypesProto3.deserializeBinary( 60*1b3f573fSAndroid Build Coastguard Worker request.getProtobufPayload()); 61*1b3f573fSAndroid Build Coastguard Worker } catch (err) { 62*1b3f573fSAndroid Build Coastguard Worker response.setParseError(err.toString()); 63*1b3f573fSAndroid Build Coastguard Worker return response; 64*1b3f573fSAndroid Build Coastguard Worker } 65*1b3f573fSAndroid Build Coastguard Worker } else if (request.getMessageType() == "protobuf_test_messages.proto2.TestAllTypesProto2"){ 66*1b3f573fSAndroid Build Coastguard Worker try { 67*1b3f573fSAndroid Build Coastguard Worker testMessage = test_messages_proto2.TestAllTypesProto2.deserializeBinary( 68*1b3f573fSAndroid Build Coastguard Worker request.getProtobufPayload()); 69*1b3f573fSAndroid Build Coastguard Worker } catch (err) { 70*1b3f573fSAndroid Build Coastguard Worker response.setParseError(err.toString()); 71*1b3f573fSAndroid Build Coastguard Worker return response; 72*1b3f573fSAndroid Build Coastguard Worker } 73*1b3f573fSAndroid Build Coastguard Worker } else { 74*1b3f573fSAndroid Build Coastguard Worker throw "Protobuf request doesn\'t have specific payload type"; 75*1b3f573fSAndroid Build Coastguard Worker } 76*1b3f573fSAndroid Build Coastguard Worker } break; 77*1b3f573fSAndroid Build Coastguard Worker 78*1b3f573fSAndroid Build Coastguard Worker case conformance.ConformanceRequest.PayloadCase.JSON_PAYLOAD: 79*1b3f573fSAndroid Build Coastguard Worker response.setSkipped("JSON not supported."); 80*1b3f573fSAndroid Build Coastguard Worker return response; 81*1b3f573fSAndroid Build Coastguard Worker 82*1b3f573fSAndroid Build Coastguard Worker case conformance.ConformanceRequest.PayloadCase.TEXT_PAYLOAD: 83*1b3f573fSAndroid Build Coastguard Worker response.setSkipped("Text format not supported."); 84*1b3f573fSAndroid Build Coastguard Worker return response; 85*1b3f573fSAndroid Build Coastguard Worker 86*1b3f573fSAndroid Build Coastguard Worker case conformance.ConformanceRequest.PayloadCase.PAYLOAD_NOT_SET: 87*1b3f573fSAndroid Build Coastguard Worker response.setRuntimeError("Request didn't have payload"); 88*1b3f573fSAndroid Build Coastguard Worker return response; 89*1b3f573fSAndroid Build Coastguard Worker } 90*1b3f573fSAndroid Build Coastguard Worker 91*1b3f573fSAndroid Build Coastguard Worker switch (request.getRequestedOutputFormat()) { 92*1b3f573fSAndroid Build Coastguard Worker case conformance.WireFormat.UNSPECIFIED: 93*1b3f573fSAndroid Build Coastguard Worker response.setRuntimeError("Unspecified output format"); 94*1b3f573fSAndroid Build Coastguard Worker return response; 95*1b3f573fSAndroid Build Coastguard Worker 96*1b3f573fSAndroid Build Coastguard Worker case conformance.WireFormat.PROTOBUF: 97*1b3f573fSAndroid Build Coastguard Worker response.setProtobufPayload(testMessage.serializeBinary()); 98*1b3f573fSAndroid Build Coastguard Worker 99*1b3f573fSAndroid Build Coastguard Worker case conformance.WireFormat.JSON: 100*1b3f573fSAndroid Build Coastguard Worker response.setSkipped("JSON not supported."); 101*1b3f573fSAndroid Build Coastguard Worker return response; 102*1b3f573fSAndroid Build Coastguard Worker 103*1b3f573fSAndroid Build Coastguard Worker default: 104*1b3f573fSAndroid Build Coastguard Worker throw "Request didn't have requested output format"; 105*1b3f573fSAndroid Build Coastguard Worker } 106*1b3f573fSAndroid Build Coastguard Worker } catch (err) { 107*1b3f573fSAndroid Build Coastguard Worker response.setRuntimeError(err.toString()); 108*1b3f573fSAndroid Build Coastguard Worker } 109*1b3f573fSAndroid Build Coastguard Worker 110*1b3f573fSAndroid Build Coastguard Worker return response; 111*1b3f573fSAndroid Build Coastguard Worker} 112*1b3f573fSAndroid Build Coastguard Worker 113*1b3f573fSAndroid Build Coastguard Workerfunction onEof(totalRead) { 114*1b3f573fSAndroid Build Coastguard Worker if (totalRead == 0) { 115*1b3f573fSAndroid Build Coastguard Worker return undefined; 116*1b3f573fSAndroid Build Coastguard Worker } else { 117*1b3f573fSAndroid Build Coastguard Worker throw "conformance_nodejs: premature EOF on stdin."; 118*1b3f573fSAndroid Build Coastguard Worker } 119*1b3f573fSAndroid Build Coastguard Worker} 120*1b3f573fSAndroid Build Coastguard Worker 121*1b3f573fSAndroid Build Coastguard Worker// Utility function to read a buffer of N bytes. 122*1b3f573fSAndroid Build Coastguard Workerfunction readBuffer(bytes) { 123*1b3f573fSAndroid Build Coastguard Worker var buf = new Buffer(bytes); 124*1b3f573fSAndroid Build Coastguard Worker var totalRead = 0; 125*1b3f573fSAndroid Build Coastguard Worker while (totalRead < bytes) { 126*1b3f573fSAndroid Build Coastguard Worker var read = 0; 127*1b3f573fSAndroid Build Coastguard Worker try { 128*1b3f573fSAndroid Build Coastguard Worker read = fs.readSync(process.stdin.fd, buf, totalRead, bytes - totalRead); 129*1b3f573fSAndroid Build Coastguard Worker } catch (e) { 130*1b3f573fSAndroid Build Coastguard Worker if (e.code == 'EOF') { 131*1b3f573fSAndroid Build Coastguard Worker return onEof(totalRead) 132*1b3f573fSAndroid Build Coastguard Worker } else if (e.code == 'EAGAIN') { 133*1b3f573fSAndroid Build Coastguard Worker } else { 134*1b3f573fSAndroid Build Coastguard Worker throw "conformance_nodejs: Error reading from stdin." + e; 135*1b3f573fSAndroid Build Coastguard Worker } 136*1b3f573fSAndroid Build Coastguard Worker } 137*1b3f573fSAndroid Build Coastguard Worker 138*1b3f573fSAndroid Build Coastguard Worker totalRead += read; 139*1b3f573fSAndroid Build Coastguard Worker } 140*1b3f573fSAndroid Build Coastguard Worker 141*1b3f573fSAndroid Build Coastguard Worker return buf; 142*1b3f573fSAndroid Build Coastguard Worker} 143*1b3f573fSAndroid Build Coastguard Worker 144*1b3f573fSAndroid Build Coastguard Workerfunction writeBuffer(buffer) { 145*1b3f573fSAndroid Build Coastguard Worker var totalWritten = 0; 146*1b3f573fSAndroid Build Coastguard Worker while (totalWritten < buffer.length) { 147*1b3f573fSAndroid Build Coastguard Worker totalWritten += fs.writeSync( 148*1b3f573fSAndroid Build Coastguard Worker process.stdout.fd, buffer, totalWritten, buffer.length - totalWritten); 149*1b3f573fSAndroid Build Coastguard Worker } 150*1b3f573fSAndroid Build Coastguard Worker} 151*1b3f573fSAndroid Build Coastguard Worker 152*1b3f573fSAndroid Build Coastguard Worker// Returns true if the test ran successfully, false on legitimate EOF. 153*1b3f573fSAndroid Build Coastguard Worker// If EOF is encountered in an unexpected place, raises IOError. 154*1b3f573fSAndroid Build Coastguard Workerfunction doTestIo() { 155*1b3f573fSAndroid Build Coastguard Worker var lengthBuf = readBuffer(4); 156*1b3f573fSAndroid Build Coastguard Worker if (!lengthBuf) { 157*1b3f573fSAndroid Build Coastguard Worker return false; 158*1b3f573fSAndroid Build Coastguard Worker } 159*1b3f573fSAndroid Build Coastguard Worker 160*1b3f573fSAndroid Build Coastguard Worker var length = lengthBuf.readInt32LE(0); 161*1b3f573fSAndroid Build Coastguard Worker var serializedRequest = readBuffer(length); 162*1b3f573fSAndroid Build Coastguard Worker if (!serializedRequest) { 163*1b3f573fSAndroid Build Coastguard Worker throw "conformance_nodejs: Failed to read request."; 164*1b3f573fSAndroid Build Coastguard Worker } 165*1b3f573fSAndroid Build Coastguard Worker 166*1b3f573fSAndroid Build Coastguard Worker serializedRequest = new Uint8Array(serializedRequest); 167*1b3f573fSAndroid Build Coastguard Worker var request = 168*1b3f573fSAndroid Build Coastguard Worker conformance.ConformanceRequest.deserializeBinary(serializedRequest); 169*1b3f573fSAndroid Build Coastguard Worker var response = doTest(request); 170*1b3f573fSAndroid Build Coastguard Worker 171*1b3f573fSAndroid Build Coastguard Worker var serializedResponse = response.serializeBinary(); 172*1b3f573fSAndroid Build Coastguard Worker 173*1b3f573fSAndroid Build Coastguard Worker lengthBuf = new Buffer(4); 174*1b3f573fSAndroid Build Coastguard Worker lengthBuf.writeInt32LE(serializedResponse.length, 0); 175*1b3f573fSAndroid Build Coastguard Worker writeBuffer(lengthBuf); 176*1b3f573fSAndroid Build Coastguard Worker writeBuffer(new Buffer(serializedResponse)); 177*1b3f573fSAndroid Build Coastguard Worker 178*1b3f573fSAndroid Build Coastguard Worker testCount += 1 179*1b3f573fSAndroid Build Coastguard Worker 180*1b3f573fSAndroid Build Coastguard Worker return true; 181*1b3f573fSAndroid Build Coastguard Worker} 182*1b3f573fSAndroid Build Coastguard Worker 183*1b3f573fSAndroid Build Coastguard Workerwhile (true) { 184*1b3f573fSAndroid Build Coastguard Worker if (!doTestIo()) { 185*1b3f573fSAndroid Build Coastguard Worker console.error('conformance_nodejs: received EOF from test runner ' + 186*1b3f573fSAndroid Build Coastguard Worker "after " + testCount + " tests, exiting") 187*1b3f573fSAndroid Build Coastguard Worker break; 188*1b3f573fSAndroid Build Coastguard Worker } 189*1b3f573fSAndroid Build Coastguard Worker} 190