1 // Copyright 2018 The Bazel Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // Integration tests for the greeter client/server
16 extern crate runfiles;
17
18 use std::io::BufRead;
19 use std::io::BufReader;
20 use std::process::{Child, Command, Stdio};
21 use std::str::FromStr;
22
23 use runfiles::Runfiles;
24
25 struct ServerInfo {
26 process: Child,
27 port: u16,
28 }
29
30 macro_rules! assert_contains {
31 ($s: expr, $e: expr) => {
32 assert!($s.find($e).is_some());
33 };
34 }
35
36 impl ServerInfo {
new() -> ServerInfo37 fn new() -> ServerInfo {
38 let r = Runfiles::create().unwrap();
39 let mut c =
40 Command::new(r.rlocation("examples/proto/helloworld/greeter_server/greeter_server"))
41 .arg("0")
42 .stdout(Stdio::piped())
43 .spawn()
44 .expect("Unable to start server");
45 let mut port: u16 = 0;
46 {
47 let mut stdout = BufReader::new(c.stdout.as_mut().expect("Failed to open stdout"));
48 let port_prefix = "greeter server started on port ";
49 while port == 0 {
50 let mut line = String::new();
51 stdout
52 .read_line(&mut line)
53 .expect("Waiting for server startup");
54 line = line.trim().to_owned();
55 if let Some(argp) = line.strip_prefix(port_prefix) {
56 port = u16::from_str(argp)
57 .unwrap_or_else(|_| panic!("Invalid port number {}", argp))
58 }
59 }
60 }
61 println!("Started server on port {port}");
62 ServerInfo { process: c, port }
63 }
64
run_client_impl(&self, arg: Option<String>) -> String65 fn run_client_impl(&self, arg: Option<String>) -> String {
66 let r = Runfiles::create().unwrap();
67
68 let mut cmd0 =
69 Command::new(r.rlocation("examples/proto/helloworld/greeter_client/greeter_client"));
70 let cmd = cmd0.arg(format!("-p={}", self.port));
71
72 let output = if let Some(s) = arg { cmd.arg(s) } else { cmd }
73 .output()
74 .expect("Unable to start client");
75 assert!(output.status.success());
76 String::from_utf8(output.stdout).expect("Non UTF-8 output from the client")
77 }
78
run_client(&self) -> String79 fn run_client(&self) -> String {
80 self.run_client_impl(None)
81 }
run_client_with_arg(&self, arg: &str) -> String82 fn run_client_with_arg(&self, arg: &str) -> String {
83 self.run_client_impl(Some(arg.to_owned()))
84 }
85
expect_log(&mut self, log: &str)86 fn expect_log(&mut self, log: &str) {
87 let mut reader =
88 BufReader::new(self.process.stdout.as_mut().expect("Failed to open stdout"));
89 let mut line = String::new();
90 reader
91 .read_line(&mut line)
92 .expect("Failed to read line from the server");
93 assert_contains!(line, log);
94 }
95
destroy(&mut self)96 fn destroy(&mut self) {
97 self.process.kill().unwrap();
98 }
99 }
100
101 #[test]
test_client_server()102 fn test_client_server() {
103 let mut s = ServerInfo::new();
104 assert_contains!(s.run_client(), "message: \"Hello world\"");
105 s.expect_log("greeting request from world");
106 assert_contains!(s.run_client_with_arg("thou"), "message: \"Hello thou\"");
107 s.expect_log("greeting request from thou");
108 s.destroy();
109 }
110