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 = Command::new(runfiles::rlocation!(
40 r,
41 "examples/proto/helloworld/greeter_server/greeter_server"
42 ))
43 .arg("0")
44 .stdout(Stdio::piped())
45 .spawn()
46 .expect("Unable to start server");
47 let mut port: u16 = 0;
48 {
49 let mut stdout = BufReader::new(c.stdout.as_mut().expect("Failed to open stdout"));
50 let port_prefix = "greeter server started on port ";
51 while port == 0 {
52 let mut line = String::new();
53 stdout
54 .read_line(&mut line)
55 .expect("Waiting for server startup");
56 line = line.trim().to_owned();
57 if let Some(argp) = line.strip_prefix(port_prefix) {
58 port = u16::from_str(argp)
59 .unwrap_or_else(|_| panic!("Invalid port number {}", argp))
60 }
61 }
62 }
63 println!("Started server on port {port}");
64 ServerInfo { process: c, port }
65 }
66
run_client_impl(&self, arg: Option<String>) -> String67 fn run_client_impl(&self, arg: Option<String>) -> String {
68 let r = Runfiles::create().unwrap();
69
70 let mut cmd0 = Command::new(runfiles::rlocation!(
71 r,
72 "examples/proto/helloworld/greeter_client/greeter_client"
73 ));
74 let cmd = cmd0.arg(format!("-p={}", self.port));
75
76 let output = if let Some(s) = arg { cmd.arg(s) } else { cmd }
77 .output()
78 .expect("Unable to start client");
79 assert!(output.status.success());
80 String::from_utf8(output.stdout).expect("Non UTF-8 output from the client")
81 }
82
run_client(&self) -> String83 fn run_client(&self) -> String {
84 self.run_client_impl(None)
85 }
run_client_with_arg(&self, arg: &str) -> String86 fn run_client_with_arg(&self, arg: &str) -> String {
87 self.run_client_impl(Some(arg.to_owned()))
88 }
89
expect_log(&mut self, log: &str)90 fn expect_log(&mut self, log: &str) {
91 let mut reader =
92 BufReader::new(self.process.stdout.as_mut().expect("Failed to open stdout"));
93 let mut line = String::new();
94 reader
95 .read_line(&mut line)
96 .expect("Failed to read line from the server");
97 assert_contains!(line, log);
98 }
99
destroy(&mut self)100 fn destroy(&mut self) {
101 self.process.kill().unwrap();
102 }
103 }
104
105 #[test]
test_client_server()106 fn test_client_server() {
107 let mut s = ServerInfo::new();
108 assert_contains!(s.run_client(), "message: \"Hello world\"");
109 s.expect_log("greeting request from world");
110 assert_contains!(s.run_client_with_arg("thou"), "message: \"Hello thou\"");
111 s.expect_log("greeting request from thou");
112 s.destroy();
113 }
114