• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2023 Google LLC.  All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 use conformance_rust_proto::{ConformanceRequest, ConformanceResponse, WireFormat};
8 
9 use protobuf::prelude::*;
10 use protobuf::Optional::{Set, Unset};
11 use protobuf::ParseError;
12 
13 use std::io::{self, ErrorKind, Read, Write};
14 use test_messages_edition2023_rust_proto::TestAllTypesEdition2023;
15 use test_messages_proto2_editions_rust_proto::TestAllTypesProto2 as EditionsTestAllTypesProto2;
16 use test_messages_proto2_rust_proto::TestAllTypesProto2;
17 use test_messages_proto3_editions_rust_proto::TestAllTypesProto3 as EditionsTestAllTypesProto3;
18 use test_messages_proto3_rust_proto::TestAllTypesProto3;
19 
20 /// Returns Some(i32) if a binary read can succeed from stdin.
21 /// Returns None if we have reached an EOF.
22 /// Panics for any other error reading.
read_little_endian_i32_from_stdin() -> Option<i32>23 fn read_little_endian_i32_from_stdin() -> Option<i32> {
24     let mut buffer = [0_u8; 4];
25     if let Err(e) = io::stdin().read_exact(&mut buffer) {
26         match e.kind() {
27             ErrorKind::UnexpectedEof => None,
28             _ => panic!("failed to read i32 from stdin"),
29         }
30     } else {
31         Some(i32::from_le_bytes(buffer))
32     }
33 }
34 
35 /// Returns Some of a conformance request read from stdin.
36 /// Returns None if we have hit an EOF that suggests the test suite is complete.
37 /// Panics in any other case (e.g. an EOF in a place that would imply a
38 /// programmer error in the conformance test suite).
read_request_from_stdin() -> Option<ConformanceRequest>39 fn read_request_from_stdin() -> Option<ConformanceRequest> {
40     let msg_len = read_little_endian_i32_from_stdin()?;
41     let mut serialized = vec![0_u8; msg_len as usize];
42     io::stdin().read_exact(&mut serialized).unwrap();
43     Some(ConformanceRequest::parse(&serialized).unwrap())
44 }
45 
write_response_to_stdout(resp: &ConformanceResponse)46 fn write_response_to_stdout(resp: &ConformanceResponse) {
47     let bytes = resp.serialize().unwrap();
48     let len = bytes.len() as u32;
49     let mut handle = io::stdout();
50     handle.write_all(&len.to_le_bytes()).unwrap();
51     handle.write(&bytes).unwrap();
52     handle.flush().unwrap();
53 }
54 
do_test(req: &ConformanceRequest) -> ConformanceResponse55 fn do_test(req: &ConformanceRequest) -> ConformanceResponse {
56     let mut resp = ConformanceResponse::new();
57     let message_type = req.message_type();
58 
59     if req.requested_output_format() != WireFormat::Protobuf {
60         resp.set_skipped("only wire format output implemented");
61         return resp;
62     }
63 
64     let bytes = match req.protobuf_payload_opt() {
65         Unset(_) => {
66             resp.set_skipped("only wire format input implemented");
67             return resp;
68         }
69         Set(bytes) => bytes,
70     };
71 
72     fn roundtrip<T: Message>(bytes: &[u8]) -> Result<Vec<u8>, ParseError> {
73         T::parse(bytes).map(|msg| msg.serialize().unwrap())
74     }
75 
76     let serialized = match message_type.as_bytes() {
77         b"protobuf_test_messages.proto2.TestAllTypesProto2" => {
78             roundtrip::<TestAllTypesProto2>(bytes)
79         }
80         b"protobuf_test_messages.proto3.TestAllTypesProto3" => {
81             roundtrip::<TestAllTypesProto3>(bytes)
82         }
83         b"protobuf_test_messages.editions.TestAllTypesEdition2023" => {
84             roundtrip::<TestAllTypesEdition2023>(bytes)
85         }
86         b"protobuf_test_messages.editions.proto2.TestAllTypesProto2" => {
87             roundtrip::<EditionsTestAllTypesProto2>(bytes)
88         }
89         b"protobuf_test_messages.editions.proto3.TestAllTypesProto3" => {
90             roundtrip::<EditionsTestAllTypesProto3>(bytes)
91         }
92         _ => panic!("unexpected msg type {message_type}"),
93     };
94 
95     match serialized {
96         Ok(serialized) => {
97             resp.set_protobuf_payload(serialized);
98         }
99         Err(_) => {
100             resp.set_parse_error("failed to parse bytes");
101         }
102     }
103 
104     resp
105 }
106 
main()107 fn main() {
108     let mut total_runs = 0;
109     while let Some(req) = read_request_from_stdin() {
110         let resp = do_test(&req);
111         write_response_to_stdout(&resp);
112         total_runs += 1;
113     }
114     eprintln!("conformance_rust: received EOF from test runner after {total_runs} tests");
115 }
116