1 // Copyright (c) 2023 Huawei Device Co., Ltd. 2 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // you may not use this file except in compliance with the License. 4 // You may obtain a copy of the License at 5 // 6 // http://www.apache.org/licenses/LICENSE-2.0 7 // 8 // Unless required by applicable law or agreed to in writing, software 9 // distributed under the License is distributed on an "AS IS" BASIS, 10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 //! HTTP [`Status Codes`]. 15 //! 16 //! The status code of a response is a three-digit integer code that describes 17 //! the result of the request and the semantics of the response, including 18 //! whether the request was successful and what content is enclosed (if any). 19 //! All valid status codes are within the range of 100 to 599, inclusive. 20 //! 21 //! [`Status Codes`]: https://httpwg.org/specs/rfc9110.html#status.codes 22 23 use core::convert::TryFrom; 24 use core::fmt::{Display, Formatter}; 25 26 use crate::error::{ErrorKind, HttpError}; 27 28 /// HTTP [`Status Codes`] implementation. 29 /// 30 /// [`Status Codes`]: https://httpwg.org/specs/rfc9110.html#status.codes 31 /// 32 /// # Examples 33 /// 34 /// ``` 35 /// use ylong_http::response::status::StatusCode; 36 /// 37 /// let status = StatusCode::OK; 38 /// ``` 39 #[derive(Debug, Clone, PartialEq, Eq)] 40 pub struct StatusCode(u16); 41 42 impl StatusCode { 43 /// Converts a `u16` to a `StatusCode`. 44 /// 45 /// # Examples 46 /// ``` 47 /// use ylong_http::response::status::StatusCode; 48 /// 49 /// assert_eq!(StatusCode::from_u16(200), Ok(StatusCode::OK)); 50 /// ``` from_u16(code: u16) -> Result<StatusCode, HttpError>51 pub fn from_u16(code: u16) -> Result<StatusCode, HttpError> { 52 // Only three-digit status codes are valid. 53 if !(100..1000).contains(&code) { 54 return Err(ErrorKind::InvalidInput.into()); 55 } 56 57 Ok(StatusCode(code)) 58 } 59 60 /// Converts a `StatusCode` to a `u16`. 61 /// 62 /// # Examples 63 /// ``` 64 /// use ylong_http::response::status::StatusCode; 65 /// 66 /// assert_eq!(StatusCode::OK.as_u16(), 200u16); 67 /// ``` as_u16(&self) -> u1668 pub fn as_u16(&self) -> u16 { 69 self.0 70 } 71 72 /// Converts a `&[u8]` to a `StatusCode`. 73 /// 74 /// # Example 75 /// ``` 76 /// use ylong_http::response::status::StatusCode; 77 /// 78 /// assert_eq!(StatusCode::from_bytes(b"200"), Ok(StatusCode::OK)); 79 /// assert!(StatusCode::from_bytes(b"0").is_err()); 80 /// ``` from_bytes(bytes: &[u8]) -> Result<Self, HttpError>81 pub fn from_bytes(bytes: &[u8]) -> Result<Self, HttpError> { 82 // Only three-digit status codes are valid. 83 if bytes.len() != 3 { 84 return Err(ErrorKind::InvalidInput.into()); 85 } 86 87 let a = bytes[0].wrapping_sub(b'0') as u16; 88 let b = bytes[1].wrapping_sub(b'0') as u16; 89 let c = bytes[2].wrapping_sub(b'0') as u16; 90 91 if a == 0 || a > 9 || b > 9 || c > 9 { 92 return Err(ErrorKind::InvalidInput.into()); 93 } 94 95 // Valid status code: 1 <= a <= 9 && 0 <= b <= 9 && 0 <= c <= 9 96 Ok(StatusCode((a * 100) + (b * 10) + c)) 97 } 98 99 /// Converts a `StatusCode` to a `[u8; 3]`. 100 /// 101 /// # Example 102 /// ``` 103 /// use ylong_http::response::status::StatusCode; 104 /// 105 /// assert_eq!(StatusCode::OK.as_bytes(), *b"200"); 106 /// ``` as_bytes(&self) -> [u8; 3]107 pub fn as_bytes(&self) -> [u8; 3] { 108 [ 109 ((self.0 / 100) as u8) + b'0', 110 (((self.0 % 100) / 10) as u8) + b'0', 111 ((self.0 % 10) as u8) + b'0', 112 ] 113 } 114 115 /// StatusCode as str. 116 // TODO: Adapter, remove it later. as_str(&self) -> String117 pub fn as_str(&self) -> String { 118 format!("{}", self.0) 119 } 120 121 /// Determines whether the `StatusCode` is [`1xx (Informational)`]. 122 /// 123 /// The 1xx (Informational) class of status code indicates an interim 124 /// response for communicating connection status or request progress prior 125 /// to completing the requested action and sending a final response. 126 /// 127 /// [`1xx (Informational)`]: https://httpwg.org/specs/rfc9110.html#status.1xx 128 /// 129 /// # Examples 130 /// ``` 131 /// use ylong_http::response::status::StatusCode; 132 /// 133 /// assert!(StatusCode::CONTINUE.is_informational()); 134 /// assert!(!StatusCode::OK.is_informational()); 135 /// ``` is_informational(&self) -> bool136 pub fn is_informational(&self) -> bool { 137 self.0 >= 100 && 200 > self.0 138 } 139 140 /// Determines whether the `StatusCode` is [`2xx (Successful)`]. 141 /// 142 /// The 2xx (Successful) class of status code indicates that the client's 143 /// request was successfully received, understood, and accepted. 144 /// 145 /// [`2xx (Successful)`]: https://httpwg.org/specs/rfc9110.html#status.2xx 146 /// 147 /// # Examples 148 /// ``` 149 /// use ylong_http::response::status::StatusCode; 150 /// 151 /// assert!(StatusCode::OK.is_successful()); 152 /// assert!(!StatusCode::CONTINUE.is_successful()); 153 /// ``` is_successful(&self) -> bool154 pub fn is_successful(&self) -> bool { 155 self.0 >= 200 && 300 > self.0 156 } 157 158 /// Determines whether the `StatusCode` is [`3xx (Redirection)`]. 159 /// 160 /// The 3xx (Redirection) class of status code indicates that further action 161 /// needs to be taken by the user agent in order to fulfill the request. 162 /// 163 /// [`3xx (Redirection)`]: https://httpwg.org/specs/rfc9110.html#status.3xx 164 /// 165 /// # Examples 166 /// ``` 167 /// use ylong_http::response::status::StatusCode; 168 /// 169 /// assert!(StatusCode::MULTIPLE_CHOICES.is_redirection()); 170 /// assert!(!StatusCode::OK.is_redirection()); 171 /// ``` is_redirection(&self) -> bool172 pub fn is_redirection(&self) -> bool { 173 self.0 >= 300 && 400 > self.0 174 } 175 176 /// Determines whether the `StatusCode` is [`4xx (Client Error)`]. 177 /// 178 /// The 4xx (Client Error) class of status code indicates that the client 179 /// seems to have erred. 180 /// 181 /// [`4xx (Client Error)`]: https://httpwg.org/specs/rfc9110.html#status.4xx 182 /// 183 /// # Examples 184 /// ``` 185 /// use ylong_http::response::status::StatusCode; 186 /// 187 /// assert!(StatusCode::BAD_REQUEST.is_client_error()); 188 /// assert!(!StatusCode::OK.is_client_error()); 189 /// ``` is_client_error(&self) -> bool190 pub fn is_client_error(&self) -> bool { 191 self.0 >= 400 && 500 > self.0 192 } 193 194 /// Determines whether the `StatusCode` is [`5xx (Server Error)`]. 195 /// 196 /// The 5xx (Server Error) class of status code indicates that the server is 197 /// aware that it has erred or is incapable of performing the requested 198 /// method. 199 /// 200 /// [`5xx (Server Error)`]: https://httpwg.org/specs/rfc9110.html#status.5xx 201 /// 202 /// # Examples 203 /// ``` 204 /// use ylong_http::response::status::StatusCode; 205 /// 206 /// assert!(StatusCode::INTERNAL_SERVER_ERROR.is_server_error()); 207 /// assert!(!StatusCode::OK.is_server_error()); 208 /// ``` is_server_error(&self) -> bool209 pub fn is_server_error(&self) -> bool { 210 self.0 >= 500 && 600 > self.0 211 } 212 } 213 214 impl TryFrom<u16> for StatusCode { 215 type Error = HttpError; 216 try_from(value: u16) -> Result<Self, Self::Error>217 fn try_from(value: u16) -> Result<Self, Self::Error> { 218 Self::from_u16(value) 219 } 220 } 221 222 impl<'a> TryFrom<&'a [u8]> for StatusCode { 223 type Error = HttpError; 224 try_from(value: &'a [u8]) -> Result<Self, Self::Error>225 fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> { 226 Self::from_bytes(value) 227 } 228 } 229 230 macro_rules! status_list { 231 ( 232 $( 233 $(#[$docs: meta])* 234 ($num:expr, $name: ident, $phrase: expr), 235 )* 236 ) => { 237 impl StatusCode { 238 $( 239 $(#[$docs])* 240 pub const $name: StatusCode = StatusCode($num as u16); 241 )* 242 243 /// Gets the reason of the `StatusCode`. 244 /// 245 /// # Examples 246 /// 247 /// ``` 248 /// use ylong_http::response::status::StatusCode; 249 /// 250 /// assert_eq!(StatusCode::OK.reason(), Some("OK")); 251 /// ``` 252 pub fn reason(&self) -> Option<&'static str> { 253 match self.0 { 254 $( 255 $num => Some($phrase), 256 )* 257 _ => None, 258 } 259 } 260 } 261 262 /// UT test cases for `StatusCode::reason`. 263 /// 264 /// # Brief 265 /// 1. Creates all the valid `StatusCode`s. 266 /// 2. Calls `StatusCode::reason` on them. 267 /// 3. Checks if the results are correct. 268 #[test] 269 pub fn ut_status_code_reason() { 270 $( 271 assert_eq!(StatusCode::from_u16($num as u16).unwrap().reason(), Some($phrase)); 272 )* 273 assert_eq!(StatusCode::from_u16(999).unwrap().reason(), None); 274 } 275 } 276 } 277 278 // TODO: Adapter, remove this later. 279 impl Display for StatusCode { fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result280 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { 281 write!( 282 f, 283 "{} {}", 284 self.as_u16(), 285 self.reason().unwrap_or("Unknown status code") 286 ) 287 } 288 } 289 290 #[rustfmt::skip] 291 status_list!( 292 /// [`100 Continue`]: https://tools.ietf.org/html/rfc7231#section-6.2.1 293 (100, CONTINUE, "Continue"), 294 295 /// [`101 Switching Protocols`]: https://tools.ietf.org/html/rfc7231#section-6.2.2 296 (101, SWITCHING_PROTOCOLS, "Switching Protocols"), 297 298 /// [`102 Processing`]: https://tools.ietf.org/html/rfc2518 299 (102, PROCESSING, "Processing"), 300 301 /// [`200 OK`]: https://tools.ietf.org/html/rfc7231#section-6.3.1 302 (200, OK, "OK"), 303 304 /// [`201 Created`]: https://tools.ietf.org/html/rfc7231#section-6.3.2 305 (201, CREATED, "Created"), 306 307 /// [`202 Accepted`]: https://tools.ietf.org/html/rfc7231#section-6.3.3 308 (202, ACCEPTED, "Accepted"), 309 310 /// [`203 Non-Authoritative Information`]: https://tools.ietf.org/html/rfc7231#section-6.3.4 311 (203, NON_AUTHORITATIVE_INFORMATION, "Non Authoritative Information"), 312 313 /// [`204 No Content`]: https://tools.ietf.org/html/rfc7231#section-6.3.5 314 (204, NO_CONTENT, "No Content"), 315 316 /// [`205 Reset Content`]: https://tools.ietf.org/html/rfc7231#section-6.3.6 317 (205, RESET_CONTENT, "Reset Content"), 318 319 /// [`206 Partial Content`]: https://tools.ietf.org/html/rfc7233#section-4.1 320 (206, PARTIAL_CONTENT, "Partial Content"), 321 322 /// [`207 Multi-Status`]: https://tools.ietf.org/html/rfc4918 323 (207, MULTI_STATUS, "Multi-Status"), 324 325 /// [`208 Already Reported`]: https://tools.ietf.org/html/rfc5842 326 (208, ALREADY_REPORTED, "Already Reported"), 327 328 /// [`226 IM Used`]: https://tools.ietf.org/html/rfc3229 329 (226, IM_USED, "IM Used"), 330 331 /// [`300 Multiple Choices`]: https://tools.ietf.org/html/rfc7231#section-6.4.1 332 (300, MULTIPLE_CHOICES, "Multiple Choices"), 333 334 /// [`301 Moved Permanently`]: https://tools.ietf.org/html/rfc7231#section-6.4.2 335 (301, MOVED_PERMANENTLY, "Moved Permanently"), 336 337 /// [`302 Found`]: https://tools.ietf.org/html/rfc7231#section-6.4.3 338 (302, FOUND, "Found"), 339 340 /// [`303 See Other`]: https://tools.ietf.org/html/rfc7231#section-6.4.4 341 (303, SEE_OTHER, "See Other"), 342 343 /// [`304 Not Modified`]: https://tools.ietf.org/html/rfc7232#section-4.1 344 (304, NOT_MODIFIED, "Not Modified"), 345 346 /// [`305 Use Proxy`]: https://tools.ietf.org/html/rfc7231#section-6.4.5 347 (305, USE_PROXY, "Use Proxy"), 348 349 /// [`307 Temporary Redirect`]: https://tools.ietf.org/html/rfc7231#section-6.4.7 350 (307, TEMPORARY_REDIRECT, "Temporary Redirect"), 351 352 /// [`308 Permanent Redirect`]: https://tools.ietf.org/html/rfc7238 353 (308, PERMANENT_REDIRECT, "Permanent Redirect"), 354 355 /// [`400 Bad Request`]: https://tools.ietf.org/html/rfc7231#section-6.5.1 356 (400, BAD_REQUEST, "Bad Request"), 357 358 /// [`401 Unauthorized`]: https://tools.ietf.org/html/rfc7235#section-3.1 359 (401, UNAUTHORIZED, "Unauthorized"), 360 361 /// [`402 Payment Required`]: https://tools.ietf.org/html/rfc7231#section-6.5.2 362 (402, PAYMENT_REQUIRED, "Payment Required"), 363 364 /// [`403 Forbidden`]: https://tools.ietf.org/html/rfc7231#section-6.5.3 365 (403, FORBIDDEN, "Forbidden"), 366 367 /// [`404 Not Found`]: https://tools.ietf.org/html/rfc7231#section-6.5.4 368 (404, NOT_FOUND, "Not Found"), 369 370 /// [`405 Method Not Allowed`]: https://tools.ietf.org/html/rfc7231#section-6.5.5 371 (405, METHOD_NOT_ALLOWED, "Method Not Allowed"), 372 373 /// [`406 Not Acceptable`]: https://tools.ietf.org/html/rfc7231#section-6.5.6 374 (406, NOT_ACCEPTABLE, "Not Acceptable"), 375 376 /// [`407 Proxy Authentication Required`]: https://tools.ietf.org/html/rfc7235#section-3.2 377 (407, PROXY_AUTHENTICATION_REQUIRED, "Proxy Authentication Required"), 378 379 /// [`408 Request Timeout`]: https://tools.ietf.org/html/rfc7231#section-6.5.7 380 (408, REQUEST_TIMEOUT, "Request Timeout"), 381 382 /// [`409 Conflict`]: https://tools.ietf.org/html/rfc7231#section-6.5.8 383 (409, CONFLICT, "Conflict"), 384 385 /// [`410 Gone`]: https://tools.ietf.org/html/rfc7231#section-6.5.9 386 (410, GONE, "Gone"), 387 388 /// [`411 Length Required`]: https://tools.ietf.org/html/rfc7231#section-6.5.10 389 (411, LENGTH_REQUIRED, "Length Required"), 390 391 /// [`412 Precondition Failed`]: https://tools.ietf.org/html/rfc7232#section-4.2 392 (412, PRECONDITION_FAILED, "Precondition Failed"), 393 394 /// [`413 Payload Too Large`]: https://tools.ietf.org/html/rfc7231#section-6.5.11 395 (413, PAYLOAD_TOO_LARGE, "Payload Too Large"), 396 397 /// [`414 URI Too Long`]: https://tools.ietf.org/html/rfc7231#section-6.5.12 398 (414, URI_TOO_LONG, "URI Too Long"), 399 400 /// [`415 Unsupported Media Type`]: https://tools.ietf.org/html/rfc7231#section-6.5.13 401 (415, UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type"), 402 403 /// [`416 Range Not Satisfiable`]: https://tools.ietf.org/html/rfc7233#section-4.4 404 (416, RANGE_NOT_SATISFIABLE, "Range Not Satisfiable"), 405 406 /// [`417 Expectation Failed`]: https://tools.ietf.org/html/rfc7231#section-6.5.14 407 (417, EXPECTATION_FAILED, "Expectation Failed"), 408 409 /// [`418 I'm a teapot`]: https://tools.ietf.org/html/rfc2324 410 (418, IM_A_TEAPOT, "I'm a teapot"), 411 412 /// [`421 Misdirected Request`]: http://tools.ietf.org/html/rfc7540#section-9.1.2 413 (421, MISDIRECTED_REQUEST, "Misdirected Request"), 414 415 /// [`422 Unprocessable Entity`]: https://tools.ietf.org/html/rfc4918 416 (422, UNPROCESSABLE_ENTITY, "Unprocessable Entity"), 417 418 /// [`423 Locked`]: https://tools.ietf.org/html/rfc4918 419 (423, LOCKED, "Locked"), 420 421 /// [`424 Failed Dependency`]: https://tools.ietf.org/html/rfc4918 422 (424, FAILED_DEPENDENCY, "Failed Dependency"), 423 424 /// [`426 Upgrade Required`]: https://tools.ietf.org/html/rfc7231#section-6.5.15 425 (426, UPGRADE_REQUIRED, "Upgrade Required"), 426 427 /// [`428 Precondition Required`]: https://tools.ietf.org/html/rfc6585 428 (428, PRECONDITION_REQUIRED, "Precondition Required"), 429 430 /// [`429 Too Many Requests`]: https://tools.ietf.org/html/rfc6585 431 (429, TOO_MANY_REQUESTS, "Too Many Requests"), 432 433 /// [`431 Request Header Fields Too Large`]: https://tools.ietf.org/html/rfc6585 434 (431, REQUEST_HEADER_FIELDS_TOO_LARGE, "Request Header Fields Too Large"), 435 436 /// [`451 Unavailable For Legal Reasons`]: http://tools.ietf.org/html/rfc7725 437 (451, UNAVAILABLE_FOR_LEGAL_REASONS, "Unavailable For Legal Reasons"), 438 439 /// [`500 Internal Server Error`]: https://tools.ietf.org/html/rfc7231#section-6.6.1 440 (500, INTERNAL_SERVER_ERROR, "Internal Server Error"), 441 442 /// [`501 Not Implemented`]: https://tools.ietf.org/html/rfc7231#section-6.6.2 443 (501, NOT_IMPLEMENTED, "Not Implemented"), 444 445 /// [`502 Bad Gateway`]: https://tools.ietf.org/html/rfc7231#section-6.6.3 446 (502, BAD_GATEWAY, "Bad Gateway"), 447 448 /// [`503 Service Unavailable`]: https://tools.ietf.org/html/rfc7231#section-6.6.4 449 (503, SERVICE_UNAVAILABLE, "Service Unavailable"), 450 451 /// [`504 Gateway Timeout`]: https://tools.ietf.org/html/rfc7231#section-6.6.5 452 (504, GATEWAY_TIMEOUT, "Gateway Timeout"), 453 454 /// [`505 HTTP Version Not Supported`]: https://tools.ietf.org/html/rfc7231#section-6.6.6 455 (505, HTTP_VERSION_NOT_SUPPORTED, "HTTP Version Not Supported"), 456 457 /// [`506 Variant Also Negotiates`]: https://tools.ietf.org/html/rfc2295 458 (506, VARIANT_ALSO_NEGOTIATES, "Variant Also Negotiates"), 459 460 /// [`507 Insufficient Storage`]: https://tools.ietf.org/html/rfc4918 461 (507, INSUFFICIENT_STORAGE, "Insufficient Storage"), 462 463 /// [`508 Loop Detected`]: https://tools.ietf.org/html/rfc5842 464 (508, LOOP_DETECTED, "Loop Detected"), 465 466 /// [`510 Not Extended`]: https://tools.ietf.org/html/rfc2774 467 (510, NOT_EXTENDED, "Not Extended"), 468 469 /// [`511 Network Authentication Required`]: https://tools.ietf.org/html/rfc6585 470 (511, NETWORK_AUTHENTICATION_REQUIRED, "Network Authentication Required"), 471 ); 472 473 #[cfg(test)] 474 mod ut_status_code { 475 use super::StatusCode; 476 use crate::error::{ErrorKind, HttpError}; 477 478 /// UT test cases for `StatusCode::from_bytes`. 479 /// 480 /// # Brief 481 /// 1. Calls `StatusCode::from_bytes` with various inputs. 482 /// 2. Checks if the results are correct. 483 #[test] ut_status_code_from_u16()484 fn ut_status_code_from_u16() { 485 // Normal Test Cases: 486 assert_eq!(StatusCode::from_u16(100), Ok(StatusCode::CONTINUE)); 487 assert!(StatusCode::from_u16(999).is_ok()); 488 489 // Exception Test Cases: 490 // 1. The given number is not in the range of 100 to 1000. 491 assert_eq!( 492 StatusCode::from_u16(0), 493 Err(HttpError::from(ErrorKind::InvalidInput)) 494 ); 495 assert_eq!( 496 StatusCode::from_u16(u16::MAX), 497 Err(HttpError::from(ErrorKind::InvalidInput)) 498 ); 499 } 500 501 /// UT test cases for `StatusCode::as_u16`. 502 /// 503 /// # Brief 504 /// 1. Creates a `StatusCode`. 505 /// 2. Calls `StatusCode::as_u16` on it. 506 /// 3. Checks if the result is correct. 507 #[test] ut_status_code_as_u16()508 fn ut_status_code_as_u16() { 509 assert_eq!(StatusCode::OK.as_u16(), 200); 510 } 511 512 /// UT test cases for `StatusCode::from_bytes`. 513 /// 514 /// # Brief 515 /// 1. Calls `StatusCode::from_bytes` with various inputs. 516 /// 2. Checks if the results are correct. 517 #[test] ut_status_code_from_bytes()518 fn ut_status_code_from_bytes() { 519 // Normal Test Cases: 520 assert_eq!(StatusCode::from_bytes(b"100"), Ok(StatusCode::CONTINUE)); 521 assert_eq!( 522 StatusCode::from_bytes(b"500"), 523 Ok(StatusCode::INTERNAL_SERVER_ERROR) 524 ); 525 assert!(StatusCode::from_bytes(b"999").is_ok()); 526 527 // Exception Test Cases: 528 // 1. Empty bytes slice. 529 assert_eq!( 530 StatusCode::from_bytes(b""), 531 Err(HttpError::from(ErrorKind::InvalidInput)) 532 ); 533 534 // 2. The length of the bytes slice is not 3. 535 assert_eq!( 536 StatusCode::from_bytes(b"1"), 537 Err(HttpError::from(ErrorKind::InvalidInput)) 538 ); 539 assert_eq!( 540 StatusCode::from_bytes(b"1000"), 541 Err(HttpError::from(ErrorKind::InvalidInput)) 542 ); 543 544 // 3. Other error branch coverage test cases. 545 assert_eq!( 546 StatusCode::from_bytes(b"099"), 547 Err(HttpError::from(ErrorKind::InvalidInput)) 548 ); 549 assert_eq!( 550 StatusCode::from_bytes(b"a99"), 551 Err(HttpError::from(ErrorKind::InvalidInput)) 552 ); 553 assert_eq!( 554 StatusCode::from_bytes(b"1a9"), 555 Err(HttpError::from(ErrorKind::InvalidInput)) 556 ); 557 assert_eq!( 558 StatusCode::from_bytes(b"19a"), 559 Err(HttpError::from(ErrorKind::InvalidInput)) 560 ); 561 assert_eq!( 562 StatusCode::from_bytes(b"\n\n\n"), 563 Err(HttpError::from(ErrorKind::InvalidInput)) 564 ); 565 } 566 567 /// UT test cases for `StatusCode::is_informational`. 568 /// 569 /// # Brief 570 /// 1. Creates some `StatusCode`s that have different type with each other. 571 /// 2. Calls `StatusCode::is_informational` on them. 572 /// 3. Checks if the results are correct. 573 #[test] ut_status_code_is_informational()574 fn ut_status_code_is_informational() { 575 assert!(StatusCode::CONTINUE.is_informational()); 576 assert!(!StatusCode::OK.is_informational()); 577 assert!(!StatusCode::MULTIPLE_CHOICES.is_informational()); 578 assert!(!StatusCode::BAD_REQUEST.is_informational()); 579 assert!(!StatusCode::INTERNAL_SERVER_ERROR.is_informational()); 580 assert!(!StatusCode::from_u16(999).unwrap().is_informational()); 581 } 582 583 /// UT test cases for `StatusCode::is_successful`. 584 /// 585 /// # Brief 586 /// 1. Creates some `StatusCode`s that have different type with each other. 587 /// 2. Calls `StatusCode::is_successful` on them. 588 /// 3. Checks if the results are correct. 589 #[test] ut_status_code_is_successful()590 fn ut_status_code_is_successful() { 591 assert!(!StatusCode::CONTINUE.is_successful()); 592 assert!(StatusCode::OK.is_successful()); 593 assert!(!StatusCode::MULTIPLE_CHOICES.is_successful()); 594 assert!(!StatusCode::BAD_REQUEST.is_successful()); 595 assert!(!StatusCode::INTERNAL_SERVER_ERROR.is_successful()); 596 assert!(!StatusCode::from_u16(999).unwrap().is_successful()); 597 } 598 599 /// UT test cases for `StatusCode::is_redirection`. 600 /// 601 /// # Brief 602 /// 1. Creates some `StatusCode`s that have different type with each other. 603 /// 2. Calls `StatusCode::is_redirection` on them. 604 /// 3. Checks if the results are correct. 605 #[test] ut_status_code_is_redirection()606 fn ut_status_code_is_redirection() { 607 assert!(!StatusCode::CONTINUE.is_redirection()); 608 assert!(!StatusCode::OK.is_redirection()); 609 assert!(StatusCode::MULTIPLE_CHOICES.is_redirection()); 610 assert!(!StatusCode::BAD_REQUEST.is_redirection()); 611 assert!(!StatusCode::INTERNAL_SERVER_ERROR.is_redirection()); 612 assert!(!StatusCode::from_u16(999).unwrap().is_redirection()); 613 } 614 615 /// UT test cases for `StatusCode::is_client_error`. 616 /// 617 /// # Brief 618 /// 1. Creates some `StatusCode`s that have different type with each other. 619 /// 2. Calls `StatusCode::is_client_error` on them. 620 /// 3. Checks if the results are correct. 621 #[test] ut_status_code_is_client_error()622 fn ut_status_code_is_client_error() { 623 assert!(!StatusCode::CONTINUE.is_client_error()); 624 assert!(!StatusCode::OK.is_client_error()); 625 assert!(!StatusCode::MULTIPLE_CHOICES.is_client_error()); 626 assert!(StatusCode::BAD_REQUEST.is_client_error()); 627 assert!(!StatusCode::INTERNAL_SERVER_ERROR.is_client_error()); 628 assert!(!StatusCode::from_u16(999).unwrap().is_client_error()); 629 } 630 631 /// UT test cases for `StatusCode::is_server_error`. 632 /// 633 /// # Brief 634 /// 1. Creates some `StatusCode`s that have different type with each other. 635 /// 2. Calls `StatusCode::is_server_error` on them. 636 /// 3. Checks if the results are correct. 637 #[test] ut_status_code_is_server_error()638 fn ut_status_code_is_server_error() { 639 assert!(!StatusCode::CONTINUE.is_server_error()); 640 assert!(!StatusCode::OK.is_server_error()); 641 assert!(!StatusCode::MULTIPLE_CHOICES.is_server_error()); 642 assert!(!StatusCode::BAD_REQUEST.is_server_error()); 643 assert!(StatusCode::INTERNAL_SERVER_ERROR.is_server_error()); 644 assert!(!StatusCode::from_u16(999).unwrap().is_server_error()); 645 } 646 647 /// UT test cases for `StatusCode::as_bytes`. 648 /// 649 /// # Brief 650 /// 1. Creates some `StatusCode`s that have different type with each other. 651 /// 2. Calls `StatusCode::as_bytes` on them. 652 /// 3. Checks if the results are correct. 653 #[test] ut_status_code_as_bytes()654 fn ut_status_code_as_bytes() { 655 assert_eq!(StatusCode::OK.as_bytes(), *b"200"); 656 assert_eq!(StatusCode::FOUND.as_bytes(), *b"302"); 657 assert_eq!(StatusCode::NOT_FOUND.as_bytes(), *b"404"); 658 assert_eq!(StatusCode::GATEWAY_TIMEOUT.as_bytes(), *b"504"); 659 } 660 } 661