/tests/server.rs

https://github.com/cargonauts-rs/cargonauts · Rust · 137 lines · 112 code · 21 blank · 4 comment · 8 complexity · 63faa80792be6c43e7a0af3f9ff9eb73 MD5 · raw file

  1. macro_rules! server {
  2. (for $test:ident use $example:expr, $port:expr ;
  3. $( $method:ident $endpoint:expr => {
  4. responds $body:expr;
  5. status $status:ident;
  6. } )*
  7. ) => {
  8. #[test]
  9. fn $test() {
  10. let mut child = serve($example, $port);
  11. let client = reqwest::Client::new().unwrap();
  12. $( request(&client,
  13. $port,
  14. reqwest::Method::$method,
  15. $endpoint,
  16. $body,
  17. reqwest::StatusCode::$status,
  18. ); )*
  19. child.kill().unwrap();
  20. }
  21. };
  22. }
  23. server! {
  24. for test_echo use "echo", 7881;
  25. Get "echo/test" => {
  26. responds "Echo { echo: \"test\" }";
  27. status Ok;
  28. }
  29. Get "echo/something" => {
  30. responds "Echo { echo: \"something\" }";
  31. status Ok;
  32. }
  33. Get "echo/test/all-caps" => {
  34. responds "Echo { echo: \"TEST\" }";
  35. status Ok;
  36. }
  37. Get "not-echo/whatever" => {
  38. responds "";
  39. status NotFound;
  40. }
  41. }
  42. server! {
  43. for test_setup use "setup", 7882;
  44. Get "my-resource/foo" => {
  45. responds "MyResource { slug: \"foo\" }";
  46. status Ok;
  47. }
  48. Get "my-resource/bar" => {
  49. responds "MyResource { slug: \"bar\" }";
  50. status Ok;
  51. }
  52. Get "my-resource/baz" => {
  53. responds "MyResource { slug: \"foo\" }";
  54. status Ok;
  55. }
  56. Get "my-resource/anything_else" => {
  57. responds ();
  58. status BadRequest;
  59. }
  60. }
  61. // Helper functions
  62. extern crate reqwest;
  63. use std::process;
  64. use std::io::{Read, BufRead, BufReader};
  65. fn serve(example: &'static str, port: u16) -> process::Child {
  66. // Spawn a server running `example`
  67. let mut cmd = process::Command::new("cargo");
  68. let mut child = cmd.arg("run").arg("--example").arg(example)
  69. .env("PORT", port.to_string())
  70. .stderr(process::Stdio::piped())
  71. .spawn().unwrap();
  72. // Wait to receiving the `Running` message and then return
  73. let mut stderr = BufReader::new(child.stderr.take().unwrap());
  74. let mut buf = String::new();
  75. loop {
  76. stderr.read_line(&mut buf).unwrap();
  77. if buf.trim().starts_with("Running") {
  78. break
  79. } {
  80. buf.clear();
  81. }
  82. }
  83. child
  84. }
  85. fn request<T: CheckBody>(
  86. client: &reqwest::Client,
  87. port: u16,
  88. method: reqwest::Method,
  89. endpoint: &'static str,
  90. body: T,
  91. status: reqwest::StatusCode,
  92. ) {
  93. let mut ctr = 10;
  94. let response = loop {
  95. match client.request(method.clone(), &format!("http://127.0.0.1:{}/{}", port, endpoint)).send() {
  96. Ok(response) => break response,
  97. _ => { ctr -= 1; if ctr == 0 { panic!() } }
  98. };
  99. };
  100. assert_eq!(response.status(), &status);
  101. body.check_body(response);
  102. }
  103. trait CheckBody {
  104. fn check_body(self, response: reqwest::Response);
  105. }
  106. impl CheckBody for &'static str {
  107. fn check_body(self, mut response: reqwest::Response) {
  108. let mut buf = String::new();
  109. response.read_to_string(&mut buf).unwrap();
  110. assert_eq!(self, &buf[..]);
  111. }
  112. }
  113. // () ignores the body
  114. impl CheckBody for () {
  115. fn check_body(self, _: reqwest::Response) { }
  116. }