2020-10-18 16:59:15 +00:00
# define CATCH_CONFIG_MAIN
2021-08-21 01:49:17 +00:00
# define CROW_ENABLE_DEBUG
2020-10-20 06:23:40 +00:00
# define CROW_LOG_LEVEL 0
2020-10-19 08:02:57 +00:00
# include <sys/stat.h>
2014-04-14 15:31:51 +00:00
# include <iostream>
2015-05-01 00:56:28 +00:00
# include <sstream>
2014-04-14 18:02:48 +00:00
# include <vector>
2020-10-27 19:53:58 +00:00
# include <thread>
# include <chrono>
2020-10-19 08:02:57 +00:00
2020-10-18 16:59:15 +00:00
# include "catch.hpp"
2020-10-19 08:02:57 +00:00
# include "crow.h"
2020-11-11 20:43:57 +00:00
# include "crow/middlewares/cookie_parser.h"
2022-02-22 14:38:51 +00:00
# include "crow/middlewares/cors.h"
2014-09-10 21:32:41 +00:00
2014-04-14 15:31:51 +00:00
using namespace std ;
2014-04-26 17:19:59 +00:00
using namespace crow ;
2014-04-14 18:02:48 +00:00
2016-03-19 15:05:48 +00:00
# define LOCALHOST_ADDRESS "127.0.0.1"
2020-10-18 16:59:15 +00:00
TEST_CASE ( " Rule " )
2014-04-14 18:02:48 +00:00
{
2021-11-25 11:45:38 +00:00
TaggedRule < > r ( " /http/ " ) ;
r . name ( " abc " ) ;
2014-04-14 20:11:37 +00:00
2021-11-25 11:45:38 +00:00
// empty handler - fail to validate
try
{
r . validate ( ) ;
FAIL_CHECK ( " empty handler should fail to validate " ) ;
}
catch ( runtime_error & e )
{
}
2014-04-14 18:02:48 +00:00
2021-11-25 11:45:38 +00:00
int x = 0 ;
2014-04-14 18:02:48 +00:00
2021-11-25 11:45:38 +00:00
// registering handler
2021-11-27 12:28:50 +00:00
r ( [ & x ] {
2021-11-27 17:44:51 +00:00
x = 1 ;
return " " ;
} ) ;
2014-04-14 20:11:37 +00:00
2021-11-25 11:45:38 +00:00
r . validate ( ) ;
2014-04-14 20:11:37 +00:00
2021-11-25 11:45:38 +00:00
response res ;
2022-02-01 13:31:05 +00:00
request req ;
2014-08-05 18:54:38 +00:00
2021-11-25 11:45:38 +00:00
// executing handler
CHECK ( 0 = = x ) ;
2022-02-01 13:31:05 +00:00
r . handle ( req , res , routing_params ( ) ) ;
2021-11-25 11:45:38 +00:00
CHECK ( 1 = = x ) ;
2014-04-21 18:27:53 +00:00
2021-11-25 11:45:38 +00:00
// registering handler with request argument
2021-11-27 12:28:50 +00:00
r ( [ & x ] ( const crow : : request & ) {
2021-11-27 17:44:51 +00:00
x = 2 ;
return " " ;
} ) ;
2014-04-21 18:27:53 +00:00
2021-11-25 11:45:38 +00:00
r . validate ( ) ;
2014-04-21 18:27:53 +00:00
2021-11-25 11:45:38 +00:00
// executing handler
CHECK ( 1 = = x ) ;
2022-02-01 13:31:05 +00:00
r . handle ( req , res , routing_params ( ) ) ;
2021-11-25 11:45:38 +00:00
CHECK ( 2 = = x ) ;
} // Rule
2014-04-14 20:11:37 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " ParameterTagging " )
2014-04-14 20:11:37 +00:00
{
2021-11-25 11:45:38 +00:00
static_assert ( black_magic : : is_valid ( " <int><int><int> " ) , " valid url " ) ;
static_assert ( ! black_magic : : is_valid ( " <int><int<<int> " ) , " invalid url " ) ;
static_assert ( ! black_magic : : is_valid ( " nt> " ) , " invalid url " ) ;
CHECK ( 1 = = black_magic : : get_parameter_tag ( " <int> " ) ) ;
CHECK ( 2 = = black_magic : : get_parameter_tag ( " <uint> " ) ) ;
CHECK ( 3 = = black_magic : : get_parameter_tag ( " <float> " ) ) ;
CHECK ( 3 = = black_magic : : get_parameter_tag ( " <double> " ) ) ;
CHECK ( 4 = = black_magic : : get_parameter_tag ( " <str> " ) ) ;
CHECK ( 4 = = black_magic : : get_parameter_tag ( " <string> " ) ) ;
CHECK ( 5 = = black_magic : : get_parameter_tag ( " <path> " ) ) ;
CHECK ( 6 * 6 + 6 + 1 = = black_magic : : get_parameter_tag ( " <int><int><int> " ) ) ;
CHECK ( 6 * 6 + 6 + 2 = = black_magic : : get_parameter_tag ( " <uint><int><int> " ) ) ;
CHECK ( 6 * 6 + 6 * 3 + 2 = =
2020-10-19 08:02:57 +00:00
black_magic : : get_parameter_tag ( " <uint><double><int> " ) ) ;
2021-11-25 11:45:38 +00:00
// url definition parsed in compile time, build into *one number*, and given
// to template argument
static_assert (
2020-10-19 08:02:57 +00:00
std : : is_same < black_magic : : S < uint64_t , double , int64_t > ,
black_magic : : arguments < 6 * 6 + 6 * 3 + 2 > : : type > : : value ,
" tag to type container " ) ;
2021-11-25 11:45:38 +00:00
} // ParameterTagging
2014-04-14 18:02:48 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " PathRouting " )
2015-01-19 10:03:06 +00:00
{
2021-11-25 11:45:38 +00:00
SimpleApp app ;
2015-01-19 10:03:06 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /file " )
2021-11-27 17:44:51 +00:00
( [ ] {
return " file " ;
} ) ;
2015-01-19 10:03:06 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /path/ " )
2021-11-27 17:44:51 +00:00
( [ ] {
return " path " ;
} ) ;
2015-01-19 10:03:06 +00:00
2021-11-25 11:45:38 +00:00
app . validate ( ) ;
2017-12-24 15:40:39 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
2015-01-19 10:03:06 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /file " ;
2015-01-19 10:03:06 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2015-01-19 10:03:06 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 200 = = res . code ) ;
}
{
request req ;
response res ;
2015-01-19 10:03:06 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /file/ " ;
2015-01-19 10:03:06 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
CHECK ( 404 = = res . code ) ;
}
{
request req ;
response res ;
2015-01-19 10:03:06 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /path " ;
2015-01-19 10:03:06 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
CHECK ( 404 ! = res . code ) ;
}
{
request req ;
response res ;
2015-01-19 10:03:06 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /path/ " ;
2015-01-19 10:03:06 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
CHECK ( 200 = = res . code ) ;
}
} // PathRouting
2015-01-19 10:03:06 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " RoutingTest " )
2014-04-15 17:57:18 +00:00
{
2021-11-25 11:45:38 +00:00
SimpleApp app ;
int A { } ;
uint32_t B { } ;
double C { } ;
string D { } ;
string E { } ;
CROW_ROUTE ( app , " /0/<uint> " )
2021-11-27 12:28:50 +00:00
( [ & ] ( uint32_t b ) {
2021-11-27 17:44:51 +00:00
B = b ;
return " OK " ;
} ) ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /1/<int>/<uint> " )
2021-11-27 12:28:50 +00:00
( [ & ] ( int a , uint32_t b ) {
2021-11-27 17:44:51 +00:00
A = a ;
B = b ;
return " OK " ;
} ) ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /4/<int>/<uint>/<double>/<string> " )
2021-11-27 12:28:50 +00:00
( [ & ] ( int a , uint32_t b , double c , string d ) {
2021-11-27 17:44:51 +00:00
A = a ;
B = b ;
C = c ;
D = d ;
return " OK " ;
} ) ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /5/<int>/<uint>/<double>/<string>/<path> " )
2021-11-27 12:28:50 +00:00
( [ & ] ( int a , uint32_t b , double c , string d , string e ) {
2021-11-27 17:44:51 +00:00
A = a ;
B = b ;
C = c ;
D = d ;
E = e ;
return " OK " ;
} ) ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
app . validate ( ) ;
// app.debug_print();
{
request req ;
response res ;
2014-08-05 18:54:38 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /-1 " ;
2014-08-05 18:54:38 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2014-08-05 18:54:38 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 404 = = res . code ) ;
}
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /0/1001999 " ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 200 = = res . code ) ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 1001999 = = B ) ;
}
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /1/-100/1999 " ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 200 = = res . code ) ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( - 100 = = A ) ;
CHECK ( 1999 = = B ) ;
}
{
request req ;
response res ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /4/5000/3/-2.71828/hellhere " ;
req . add_header ( " TestHeader " , " Value " ) ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 200 = = res . code ) ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 5000 = = A ) ;
CHECK ( 3 = = B ) ;
CHECK ( - 2.71828 = = C ) ;
CHECK ( " hellhere " = = D ) ;
}
{
request req ;
response res ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /5/-5/999/3.141592/hello_there/a/b/c/d " ;
req . add_header ( " TestHeader " , " Value " ) ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 200 = = res . code ) ;
2014-04-15 17:57:18 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( - 5 = = A ) ;
CHECK ( 999 = = B ) ;
CHECK ( 3.141592 = = C ) ;
CHECK ( " hello_there " = = D ) ;
CHECK ( " a/b/c/d " = = E ) ;
}
} // RoutingTest
2014-04-15 17:57:18 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " simple_response_routing_params " )
2014-04-14 20:11:37 +00:00
{
2021-11-25 11:45:38 +00:00
CHECK ( 100 = = response ( 100 ) . code ) ;
CHECK ( 200 = = response ( " Hello there " ) . code ) ;
CHECK ( 500 = = response ( 500 , " Internal Error? " ) . code ) ;
CHECK ( 100 = = response ( 100 , " xml " , " " ) . code ) ;
CHECK ( " text/xml " = = response ( 100 , " xml " , " " ) . get_header_value ( " Content-Type " ) ) ;
CHECK ( 200 = = response ( 200 , " html " , " " ) . code ) ;
CHECK ( " text/html " = = response ( 200 , " html " , " " ) . get_header_value ( " Content-Type " ) ) ;
CHECK ( 500 = = response ( 500 , " html " , " Internal Error? " ) . code ) ;
CHECK ( " text/css " = = response ( 500 , " css " , " Internal Error? " ) . get_header_value ( " Content-Type " ) ) ;
routing_params rp ;
rp . int_params . push_back ( 1 ) ;
rp . int_params . push_back ( 5 ) ;
rp . uint_params . push_back ( 2 ) ;
rp . double_params . push_back ( 3 ) ;
rp . string_params . push_back ( " hello " ) ;
CHECK ( 1 = = rp . get < int64_t > ( 0 ) ) ;
CHECK ( 5 = = rp . get < int64_t > ( 1 ) ) ;
CHECK ( 2 = = rp . get < uint64_t > ( 0 ) ) ;
CHECK ( 3 = = rp . get < double > ( 0 ) ) ;
CHECK ( " hello " = = rp . get < string > ( 0 ) ) ;
} // simple_response_routing_params
2014-04-14 18:02:48 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " handler_with_response " )
2014-08-05 13:38:51 +00:00
{
2021-11-25 11:45:38 +00:00
SimpleApp app ;
CROW_ROUTE ( app , " / " )
( [ ] ( const crow : : request & , crow : : response & ) { } ) ;
} // handler_with_response
2014-08-05 13:38:51 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " http_method " )
2014-10-07 12:51:24 +00:00
{
2021-11-25 11:45:38 +00:00
SimpleApp app ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " / " ) . methods ( " POST " _method ,
2021-11-27 12:28:50 +00:00
" GET " _method ) ( [ ] ( const request & req ) {
2021-11-27 17:44:51 +00:00
if ( req . method = = " GET " _method )
return " 2 " ;
else
return " 1 " ;
} ) ;
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /get_only " )
2021-11-27 17:44:51 +00:00
. methods ( " GET " _method ) ( [ ] ( const request & /*req*/ ) {
return " get " ;
} ) ;
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /post_only " )
2021-11-27 17:44:51 +00:00
. methods ( " POST " _method ) ( [ ] ( const request & /*req*/ ) {
return " post " ;
} ) ;
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /patch_only " )
2021-11-27 17:44:51 +00:00
. methods ( " PATCH " _method ) ( [ ] ( const request & /*req*/ ) {
return " patch " ;
} ) ;
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /purge_only " )
2021-11-27 17:44:51 +00:00
. methods ( " PURGE " _method ) ( [ ] ( const request & /*req*/ ) {
return " purge " ;
} ) ;
2014-10-07 12:51:24 +00:00
2021-11-25 11:45:38 +00:00
app . validate ( ) ;
app . debug_print ( ) ;
2014-10-07 12:51:24 +00:00
2021-11-25 11:45:38 +00:00
// cannot have multiple handlers for the same url
// CROW_ROUTE(app, "/")
//.methods("GET"_method)
//([]{ return "2"; });
2014-10-07 12:51:24 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
2014-10-07 12:51:24 +00:00
2021-11-25 11:45:38 +00:00
req . url = " / " ;
app . handle ( req , res ) ;
2014-10-07 12:51:24 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( " 2 " = = res . body ) ;
}
{
request req ;
response res ;
2014-10-07 12:51:24 +00:00
2021-11-25 11:45:38 +00:00
req . url = " / " ;
req . method = " POST " _method ;
app . handle ( req , res ) ;
2014-10-07 12:51:24 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( " 1 " = = res . body ) ;
}
2014-10-07 12:51:24 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
2017-10-05 15:13:40 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /get_only " ;
app . handle ( req , res ) ;
2017-10-05 15:13:40 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( " get " = = res . body ) ;
}
2017-10-05 15:13:40 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
2017-10-21 12:20:07 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /patch_only " ;
req . method = " PATCH " _method ;
app . handle ( req , res ) ;
2017-10-21 12:20:07 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( " patch " = = res . body ) ;
}
2017-10-21 12:20:07 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
2014-10-07 12:51:24 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /purge_only " ;
req . method = " PURGE " _method ;
app . handle ( req , res ) ;
2014-10-07 12:51:24 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( " purge " = = res . body ) ;
}
2014-10-07 12:51:24 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
2020-10-14 22:24:26 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /get_only " ;
req . method = " POST " _method ;
app . handle ( req , res ) ;
2020-10-14 22:24:26 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( " get " ! = res . body ) ;
}
2021-04-03 03:00:23 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
2021-04-03 03:00:23 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /get_only " ;
req . method = " POST " _method ;
app . handle ( req , res ) ;
2021-04-03 03:00:23 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 405 = = res . code ) ;
}
2021-04-03 03:00:23 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
2021-04-03 03:00:23 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /get_only " ;
req . method = " HEAD " _method ;
app . handle ( req , res ) ;
2021-04-03 03:00:23 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 200 = = res . code ) ;
CHECK ( " " = = res . body ) ;
}
2021-04-03 03:00:23 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
2021-04-03 03:00:23 +00:00
2021-11-25 11:45:38 +00:00
req . url = " / " ;
req . method = " OPTIONS " _method ;
app . handle ( req , res ) ;
2021-04-03 03:00:23 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 204 = = res . code ) ;
CHECK ( " OPTIONS, HEAD, GET, POST " = = res . get_header_value ( " Allow " ) ) ;
}
2021-04-03 03:00:23 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
2021-04-03 03:00:23 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /does_not_exist " ;
req . method = " OPTIONS " _method ;
app . handle ( req , res ) ;
2021-04-03 03:00:23 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 404 = = res . code ) ;
}
2021-04-03 03:00:23 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
req . url = " /* " ;
req . method = " OPTIONS " _method ;
app . handle ( req , res ) ;
CHECK ( 204 = = res . code ) ;
CHECK ( " OPTIONS, HEAD, GET, POST, PATCH, PURGE " = = res . get_header_value ( " Allow " ) ) ;
}
} // http_method
2014-10-07 12:51:24 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " server_handling_error_request " )
2014-04-22 11:19:03 +00:00
{
2021-11-25 11:45:38 +00:00
static char buf [ 2048 ] ;
SimpleApp app ;
CROW_ROUTE ( app , " / " )
2021-11-27 17:44:51 +00:00
( [ ] {
return " A " ;
} ) ;
2021-11-25 11:45:38 +00:00
// Server<SimpleApp> server(&app, LOCALHOST_ADDRESS, 45451);
// auto _ = async(launch::async, [&]{server.run();});
2022-03-10 12:44:39 +00:00
auto _ = app . bindaddr ( LOCALHOST_ADDRESS ) . port ( 45451 ) . run_async ( ) ;
2021-11-25 11:45:38 +00:00
app . wait_for_server_start ( ) ;
std : : string sendmsg = " POX " ;
asio : : io_service is ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
c . send ( asio : : buffer ( sendmsg ) ) ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
try
{
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
FAIL_CHECK ( ) ;
}
catch ( std : : exception & e )
{
CROW_LOG_DEBUG < < e . what ( ) ;
}
2021-11-01 09:02:25 +00:00
}
2021-11-25 11:45:38 +00:00
app . stop ( ) ;
} // server_handling_error_request
2021-11-01 09:02:25 +00:00
TEST_CASE ( " server_handling_error_request_http_version " )
{
2021-11-25 11:45:38 +00:00
static char buf [ 2048 ] ;
SimpleApp app ;
CROW_ROUTE ( app , " / " )
2021-11-27 17:44:51 +00:00
( [ ] {
return " A " ;
} ) ;
2022-03-10 12:44:39 +00:00
auto _ = app . bindaddr ( LOCALHOST_ADDRESS ) . port ( 45451 ) . run_async ( ) ;
2021-11-25 11:45:38 +00:00
app . wait_for_server_start ( ) ;
std : : string sendmsg = " POST / \r \n Content-Length:3 \r \n X-HeaderTest: 123 \r \n \r \n A=B \r \n " ;
asio : : io_service is ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
2021-11-01 09:02:25 +00:00
2021-11-25 11:45:38 +00:00
c . send ( asio : : buffer ( sendmsg ) ) ;
2021-11-01 09:02:25 +00:00
2021-11-25 11:45:38 +00:00
try
{
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
FAIL_CHECK ( ) ;
}
catch ( std : : exception & e )
{
CROW_LOG_DEBUG < < e . what ( ) ;
}
2014-04-22 11:19:03 +00:00
}
2021-11-25 11:45:38 +00:00
app . stop ( ) ;
} // server_handling_error_request_http_version
2014-04-22 11:19:03 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " multi_server " )
2014-04-15 13:08:23 +00:00
{
2021-11-25 11:45:38 +00:00
static char buf [ 2048 ] ;
SimpleApp app1 , app2 ;
CROW_ROUTE ( app1 , " / " ) . methods ( " GET " _method ,
2021-11-27 17:44:51 +00:00
" POST " _method ) ( [ ] {
return " A " ;
} ) ;
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app2 , " / " ) . methods ( " GET " _method ,
2021-11-27 17:44:51 +00:00
" POST " _method ) ( [ ] {
return " B " ;
} ) ;
2021-11-25 11:45:38 +00:00
2022-03-10 12:44:39 +00:00
auto _ = app1 . bindaddr ( LOCALHOST_ADDRESS ) . port ( 45451 ) . run_async ( ) ;
auto _2 = app2 . bindaddr ( LOCALHOST_ADDRESS ) . port ( 45452 ) . run_async ( ) ;
2021-11-25 11:45:38 +00:00
app1 . wait_for_server_start ( ) ;
app2 . wait_for_server_start ( ) ;
std : : string sendmsg =
2021-11-01 18:10:45 +00:00
" POST / HTTP/1.0 \r \n Content-Length:3 \r \n X-HeaderTest: 123 \r \n \r \n A=B \r \n " ;
2021-11-25 11:45:38 +00:00
{
asio : : io_service is ;
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
c . send ( asio : : buffer ( sendmsg ) ) ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
size_t recved = c . receive ( asio : : buffer ( buf , 2048 ) ) ;
CHECK ( ' A ' = = buf [ recved - 1 ] ) ;
}
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
{
asio : : io_service is ;
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45452 ) ) ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
for ( auto ch : sendmsg )
{
char buf [ 1 ] = { ch } ;
c . send ( asio : : buffer ( buf ) ) ;
}
2014-04-15 13:08:23 +00:00
2021-11-25 11:45:38 +00:00
size_t recved = c . receive ( asio : : buffer ( buf , 2048 ) ) ;
CHECK ( ' B ' = = buf [ recved - 1 ] ) ;
}
2014-04-15 13:08:23 +00:00
2021-11-25 11:45:38 +00:00
app1 . stop ( ) ;
app2 . stop ( ) ;
} // multi_server
2014-04-15 13:08:23 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " json_read " )
2014-04-18 22:12:56 +00:00
{
2021-11-25 11:45:38 +00:00
{
const char * json_error_tests [ ] = {
" {} 3 " ,
" {{} " ,
" {3} " ,
" 3.4.5 " ,
" +3 " ,
" 3-2 " ,
" 00 " ,
" 03 " ,
" 1e3e3 " ,
" 1e+.3 " ,
" nll " ,
" f " ,
" t " ,
" { \" x \" :3,} " ,
" { \" x \" } " ,
" { \" x \" :3 q} " ,
" { \" x \" :[3 4]} " ,
" { \" x \" :[ \" " ,
" { \" x \" :[[], 4], \" y \" ,} " ,
" { \" x \" :[3 " ,
" { \" x \" :[ null, false, true} " ,
} ;
for ( auto s : json_error_tests )
{
auto x = json : : load ( s ) ;
if ( x )
{
FAIL_CHECK ( std : : string ( " should fail to parse " ) + s ) ;
return ;
}
}
2020-10-19 08:02:57 +00:00
}
2021-11-25 11:45:38 +00:00
auto x = json : : load ( R " ({ " message " : " hello , world " }) " ) ;
if ( ! x ) FAIL_CHECK ( " fail to parse " ) ;
CHECK ( " hello, world " = = x [ " message " ] ) ;
CHECK ( 1 = = x . size ( ) ) ;
CHECK ( false = = x . has ( " mess " ) ) ;
REQUIRE_THROWS ( x [ " mess " ] ) ;
2022-02-05 15:15:19 +00:00
// TODO(ipkn) returning false is better than exception
2021-11-25 11:45:38 +00:00
// ASSERT_THROW(3 == x["message"]);
CHECK ( 12 = = x [ " message " ] . size ( ) ) ;
std : : string s =
2020-10-19 08:02:57 +00:00
R " ({ " int " :3, " ints " :[1,2,3,4,5], " bigint " :1234567890 }) " ;
2021-11-25 11:45:38 +00:00
auto y = json : : load ( s ) ;
CHECK ( 3 = = y [ " int " ] ) ;
CHECK ( 3.0 = = y [ " int " ] ) ;
CHECK ( 3.01 ! = y [ " int " ] ) ;
CHECK ( 5 = = y [ " ints " ] . size ( ) ) ;
CHECK ( 1 = = y [ " ints " ] [ 0 ] ) ;
CHECK ( 2 = = y [ " ints " ] [ 1 ] ) ;
CHECK ( 3 = = y [ " ints " ] [ 2 ] ) ;
CHECK ( 4 = = y [ " ints " ] [ 3 ] ) ;
CHECK ( 5 = = y [ " ints " ] [ 4 ] ) ;
CHECK ( 1u = = y [ " ints " ] [ 0 ] ) ;
CHECK ( 1.f = = y [ " ints " ] [ 0 ] ) ;
int q = ( int ) y [ " ints " ] [ 1 ] ;
CHECK ( 2 = = q ) ;
q = y [ " ints " ] [ 2 ] . i ( ) ;
CHECK ( 3 = = q ) ;
CHECK ( 1234567890 = = y [ " bigint " ] ) ;
std : : string s2 = R " ({ " bools " :[true, false], " doubles " :[1.2, -3.4]}) " ;
auto z = json : : load ( s2 ) ;
CHECK ( 2 = = z [ " bools " ] . size ( ) ) ;
CHECK ( 2 = = z [ " doubles " ] . size ( ) ) ;
CHECK ( true = = z [ " bools " ] [ 0 ] . b ( ) ) ;
CHECK ( false = = z [ " bools " ] [ 1 ] . b ( ) ) ;
CHECK ( 1.2 = = z [ " doubles " ] [ 0 ] . d ( ) ) ;
CHECK ( - 3.4 = = z [ " doubles " ] [ 1 ] . d ( ) ) ;
std : : string s3 = R " ({ " uint64 " : 18446744073709551615}) " ;
auto z1 = json : : load ( s3 ) ;
CHECK ( 18446744073709551615ull = = z1 [ " uint64 " ] . u ( ) ) ;
std : : ostringstream os ;
os < < z1 [ " uint64 " ] ;
CHECK ( " 18446744073709551615 " = = os . str ( ) ) ;
} // json_read
2014-04-18 22:12:56 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " json_read_real " )
2014-11-08 23:47:45 +00:00
{
2021-11-25 11:45:38 +00:00
vector < std : : string > v { " 0.036303908355795146 " ,
" 0.18320417789757412 " ,
" 0.05319940476190476 " ,
" 0.15224702380952382 " ,
" 0 " ,
" 0.3296201145552561 " ,
" 0.47921580188679247 " ,
" 0.05873511904761905 " ,
" 0.1577827380952381 " ,
" 0.4996841307277628 " ,
" 0.6425412735849056 " ,
" 0.052113095238095236 " ,
" 0.12830357142857143 " ,
" 0.7871041105121294 " ,
" 0.954220013477089 " ,
" 0.05869047619047619 " ,
" 0.1625 " ,
" 0.8144794474393531 " ,
" 0.9721613881401617 " ,
" 0.1399404761904762 " ,
" 0.24470238095238095 " ,
" 0.04527459568733154 " ,
" 0.2096950808625337 " ,
" 0.35267857142857145 " ,
" 0.42791666666666667 " ,
" 0.855731974393531 " ,
" 0.9352467991913747 " ,
" 0.3816220238095238 " ,
" 0.4282886904761905 " ,
" 0.39414167789757415 " ,
" 0.5316079851752021 " ,
" 0.3809375 " ,
" 0.4571279761904762 " ,
" 0.03522995283018868 " ,
" 0.1915641846361186 " ,
" 0.6164136904761904 " ,
" 0.7192708333333333 " ,
" 0.05675117924528302 " ,
" 0.21308541105121293 " ,
" 0.7045386904761904 " ,
" 0.8016815476190476 " } ;
for ( auto x : v )
{
CROW_LOG_DEBUG < < x ;
CHECK ( json : : load ( x ) . d ( ) = = boost : : lexical_cast < double > ( x ) ) ;
}
auto ret = json : : load (
2020-10-19 08:02:57 +00:00
R " ---({ " balloons " :[{ " mode " : " ellipse " , " left " :0.036303908355795146, " right " :0.18320417789757412, " top " :0.05319940476190476, " bottom " :0.15224702380952382, " index " : " 0 " },{ " mode " : " ellipse " , " left " :0.3296201145552561, " right " :0.47921580188679247, " top " :0.05873511904761905, " bottom " :0.1577827380952381, " index " : " 1 " },{ " mode " : " ellipse " , " left " :0.4996841307277628, " right " :0.6425412735849056, " top " :0.052113095238095236, " bottom " :0.12830357142857143, " index " : " 2 " },{ " mode " : " ellipse " , " left " :0.7871041105121294, " right " :0.954220013477089, " top " :0.05869047619047619, " bottom " :0.1625, " index " : " 3 " },{ " mode " : " ellipse " , " left " :0.8144794474393531, " right " :0.9721613881401617, " top " :0.1399404761904762, " bottom " :0.24470238095238095, " index " : " 4 " },{ " mode " : " ellipse " , " left " :0.04527459568733154, " right " :0.2096950808625337, " top " :0.35267857142857145, " bottom " :0.42791666666666667, " index " : " 5 " },{ " mode " : " ellipse " , " left " :0.855731974393531, " right " :0.9352467991913747, " top " :0.3816220238095238, " bottom " :0.4282886904761905, " index " : " 6 " },{ " mode " : " ellipse " , " left " :0.39414167789757415, " right " :0.5316079851752021, " top " :0.3809375, " bottom " :0.4571279761904762, " index " : " 7 " },{ " mode " : " ellipse " , " left " :0.03522995283018868, " right " :0.1915641846361186, " top " :0.6164136904761904, " bottom " :0.7192708333333333, " index " : " 8 " },{ " mode " : " ellipse " , " left " :0.05675117924528302, " right " :0.21308541105121293, " top " :0.7045386904761904, " bottom " :0.8016815476190476, " index " : " 9 " }]})--- " ) ;
2021-11-25 11:45:38 +00:00
CHECK ( ret ) ;
} // json_read_real
2014-11-08 23:47:45 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " json_read_unescaping " )
2014-08-01 21:30:36 +00:00
{
2021-11-25 11:45:38 +00:00
{
auto x = json : : load ( R " ({ " data " : " \ ud55c \ n \ t \ r " }) " ) ;
if ( ! x )
{
FAIL_CHECK ( " fail to parse " ) ;
return ;
}
CHECK ( 6 = = x [ " data " ] . size ( ) ) ;
CHECK ( " 한 \n \t \r " = = x [ " data " ] ) ;
}
{
// multiple r_string instance
auto x = json : : load ( R " ({ " data " : " \ ud55c \ n \ t \ r " }) " ) ;
auto a = x [ " data " ] . s ( ) ;
auto b = x [ " data " ] . s ( ) ;
CHECK ( 6 = = a . size ( ) ) ;
CHECK ( 6 = = b . size ( ) ) ;
CHECK ( 6 = = x [ " data " ] . size ( ) ) ;
}
} // json_read_unescaping
2014-08-01 21:30:36 +00:00
2021-05-12 12:45:55 +00:00
TEST_CASE ( " json_read_string " )
{
auto x = json : : load ( R " ({ " message " : 53}) " ) ;
2021-11-25 11:45:38 +00:00
int y ( x [ " message " ] ) ;
2021-05-12 12:45:55 +00:00
std : : string z ( x [ " message " ] ) ;
CHECK ( 53 = = y ) ;
CHECK ( " 53 " = = z ) ;
2021-11-25 11:45:38 +00:00
} // json_read_string
2021-05-12 12:45:55 +00:00
TEST_CASE ( " json_read_container " )
{
auto x = json : : load ( R " ({ " first " : 53, " second " : " 55 " , " third " : [5,6,7,8,3,2,1,4]}) " ) ;
CHECK ( std : : vector < std : : string > ( { " first " , " second " , " third " } ) = = x . keys ( ) ) ;
CHECK ( 53 = = int ( x . lo ( ) [ 0 ] ) ) ;
CHECK ( " 55 " = = std : : string ( x . lo ( ) [ 1 ] ) ) ;
2021-11-25 11:45:38 +00:00
CHECK ( 8 = = int ( x . lo ( ) [ 2 ] . lo ( ) [ 3 ] ) ) ;
} // json_read_container
2021-05-12 12:45:55 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " json_write " )
2014-04-17 13:32:21 +00:00
{
2021-11-25 11:45:38 +00:00
json : : wvalue x ;
x [ " message " ] = " hello world " ;
CHECK ( R " ({ " message " : " hello world " }) " = = x . dump ( ) ) ;
x [ " message " ] = std : : string ( " string value " ) ;
CHECK ( R " ({ " message " : " string value " }) " = = x . dump ( ) ) ;
x [ " message " ] [ " x " ] = 3 ;
CHECK ( R " ({ " message " :{ " x " :3}}) " = = x . dump ( ) ) ;
x [ " message " ] [ " y " ] = 5 ;
CHECK ( ( R " ({ " message " :{ " x " :3, " y " :5}}) " = = x . dump ( ) | |
2021-01-05 14:49:10 +00:00
R " ({ " message " :{ " y " :5, " x " :3}}) " = = x . dump ( ) ) ) ;
2021-11-25 11:45:38 +00:00
x [ " message " ] = 5.5 ;
CHECK ( R " ({ " message " :5.5}) " = = x . dump ( ) ) ;
x [ " message " ] = 1234567890 ;
CHECK ( R " ({ " message " :1234567890}) " = = x . dump ( ) ) ;
2014-04-17 13:32:21 +00:00
2021-11-25 11:45:38 +00:00
json : : wvalue y ;
y [ " scores " ] [ 0 ] = 1 ;
y [ " scores " ] [ 1 ] = " king " ;
y [ " scores " ] [ 2 ] = 3.5 ;
CHECK ( R " ({ " scores " :[1, " king " ,3.5]}) " = = y . dump ( ) ) ;
2017-10-22 11:31:17 +00:00
2021-11-25 11:45:38 +00:00
y [ " scores " ] [ 2 ] [ 0 ] = " real " ;
y [ " scores " ] [ 2 ] [ 1 ] = false ;
y [ " scores " ] [ 2 ] [ 2 ] = true ;
CHECK ( R " ({ " scores " :[1, " king " ,[ " real " ,false,true]]}) " = = y . dump ( ) ) ;
2021-08-20 00:57:21 +00:00
2021-11-25 11:45:38 +00:00
y [ " scores " ] [ " a " ] [ " b " ] [ " c " ] = nullptr ;
CHECK ( R " ({ " scores " :{ " a " :{ " b " :{ " c " :null}}}}) " = = y . dump ( ) ) ;
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
y [ " scores " ] = std : : vector < int > { 1 , 2 , 3 } ;
CHECK ( R " ({ " scores " :[1,2,3]}) " = = y . dump ( ) ) ;
} // json_write
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json_copy_r_to_w_to_w_to_r " )
{
json : : rvalue r = json : : load (
R " ({ " smallint " :2, " bigint " :2147483647, " fp " :23.43, " fpsc " :2.343e1, " str " : " a string " , " trueval " :true, " falseval " :false, " nullval " :null, " listval " :[1,2, " foo " , " bar " ], " obj " :{ " member " :23, " other " : " baz " }}) " ) ;
json : : wvalue v { r } ;
json : : wvalue w ( v ) ;
json : : rvalue x =
json : : load ( w . dump ( ) ) ; // why no copy-ctor wvalue -> rvalue?
CHECK ( 2 = = x [ " smallint " ] ) ;
CHECK ( 2147483647 = = x [ " bigint " ] ) ;
CHECK ( 23.43 = = x [ " fp " ] ) ;
CHECK ( 23.43 = = x [ " fpsc " ] ) ;
CHECK ( " a string " = = x [ " str " ] ) ;
CHECK ( x [ " trueval " ] . b ( ) ) ;
REQUIRE_FALSE ( x [ " falseval " ] . b ( ) ) ;
CHECK ( json : : type : : Null = = x [ " nullval " ] . t ( ) ) ;
CHECK ( 4u = = x [ " listval " ] . size ( ) ) ;
CHECK ( 1 = = x [ " listval " ] [ 0 ] ) ;
CHECK ( 2 = = x [ " listval " ] [ 1 ] ) ;
CHECK ( " foo " = = x [ " listval " ] [ 2 ] ) ;
CHECK ( " bar " = = x [ " listval " ] [ 3 ] ) ;
CHECK ( 23 = = x [ " obj " ] [ " member " ] ) ;
CHECK ( " member " = = x [ " obj " ] [ " member " ] . key ( ) ) ;
CHECK ( " baz " = = x [ " obj " ] [ " other " ] ) ;
CHECK ( " other " = = x [ " obj " ] [ " other " ] . key ( ) ) ;
} // json_copy_r_to_w_to_w_to_r
2022-02-05 15:15:19 +00:00
//TODO(EDev): maybe combine these
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(bool) " )
{
CHECK ( json : : wvalue ( true ) . t ( ) = = json : : type : : True ) ;
CHECK ( json : : wvalue ( false ) . t ( ) = = json : : type : : False ) ;
} // json::wvalue::wvalue(bool)
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(std::uint8_t) " )
{
std : : uint8_t i = 42 ;
json : : wvalue value = i ;
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( value . t ( ) = = json : : type : : Number ) ;
CHECK ( value . dump ( ) = = " 42 " ) ;
} // json::wvalue::wvalue(std::uint8_t)
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(std::uint16_t) " )
{
std : : uint16_t i = 42 ;
json : : wvalue value = i ;
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( value . t ( ) = = json : : type : : Number ) ;
CHECK ( value . dump ( ) = = " 42 " ) ;
} // json::wvalue::wvalue(std::uint16_t)
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(std::uint32_t) " )
{
std : : uint32_t i = 42 ;
json : : wvalue value = i ;
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( value . t ( ) = = json : : type : : Number ) ;
CHECK ( value . dump ( ) = = " 42 " ) ;
} // json::wvalue::wvalue(std::uint32_t)
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(std::uint64_t) " )
{
std : : uint64_t i = 42 ;
json : : wvalue value = i ;
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( value . t ( ) = = json : : type : : Number ) ;
CHECK ( value . dump ( ) = = " 42 " ) ;
} // json::wvalue::wvalue(std::uint64_t)
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(std::int8_t) " )
{
std : : int8_t i = - 42 ;
json : : wvalue value = i ;
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( value . t ( ) = = json : : type : : Number ) ;
CHECK ( value . dump ( ) = = " -42 " ) ;
} // json::wvalue::wvalue(std::int8_t)
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(std::int16_t) " )
{
std : : int16_t i = - 42 ;
json : : wvalue value = i ;
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( value . t ( ) = = json : : type : : Number ) ;
CHECK ( value . dump ( ) = = " -42 " ) ;
} // json::wvalue::wvalue(std::int16_t)
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(std::int32_t) " )
{
std : : int32_t i = - 42 ;
json : : wvalue value = i ;
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( value . t ( ) = = json : : type : : Number ) ;
CHECK ( value . dump ( ) = = " -42 " ) ;
} // json::wvalue::wvalue(std::int32_t)
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(std::int64_t) " )
{
std : : int64_t i = - 42 ;
json : : wvalue value = i ;
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( value . t ( ) = = json : : type : : Number ) ;
CHECK ( value . dump ( ) = = " -42 " ) ;
} // json::wvalue::wvalue(std::int64_t)
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(float) " )
{
float f = 4.2 ;
json : : wvalue value = f ;
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( value . t ( ) = = json : : type : : Number ) ;
CHECK ( value . dump ( ) = = " 4.2 " ) ;
} // json::wvalue::wvalue(float)
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(double) " )
{
double d = 4.2 ;
json : : wvalue value = d ;
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( value . t ( ) = = json : : type : : Number ) ;
CHECK ( value . dump ( ) = = " 4.2 " ) ;
} // json::wvalue::wvalue(double)
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(char const*) " )
{
char const * str = " Hello world! " ;
json : : wvalue value = str ;
2021-08-09 12:31:28 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( value . t ( ) = = json : : type : : String ) ;
CHECK ( value . dump ( ) = = " \" Hello world! \" " ) ;
} // json::wvalue::wvalue(char const*)
2021-08-06 16:37:18 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(std::string const&) " )
{
std : : string str = " Hello world! " ;
json : : wvalue value = str ;
2021-08-06 16:37:18 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( value . t ( ) = = json : : type : : String ) ;
CHECK ( value . dump ( ) = = " \" Hello world! \" " ) ;
} // json::wvalue::wvalue(std::string const&)
2021-08-06 16:37:18 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(std::string&&) " )
{
std : : string str = " Hello world! " ;
json : : wvalue value = std : : move ( str ) ;
2021-08-06 16:37:18 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( value . t ( ) = = json : : type : : String ) ;
CHECK ( value . dump ( ) = = " \" Hello world! \" " ) ;
} // json::wvalue::wvalue(std::string&&)
2021-08-06 16:37:18 +00:00
2021-11-25 11:45:38 +00:00
TEST_CASE ( " json::wvalue::wvalue(std::initializer_list<std::pair<std::string const, json::wvalue>>) " )
{
json : : wvalue integer , number , truth , lie , null ;
integer = 2147483647 ;
number = 23.43 ;
truth = true ;
lie = false ;
/* initializer-list constructor. */
json : : wvalue value ( { { " integer " , integer } ,
{ " number " , number } ,
{ " truth " , truth } ,
{ " lie " , lie } ,
{ " null " , null } } ) ;
CHECK ( value [ " integer " ] . dump ( ) = = integer . dump ( ) ) ;
CHECK ( value [ " number " ] . dump ( ) = = number . dump ( ) ) ;
CHECK ( value [ " truth " ] . dump ( ) = = truth . dump ( ) ) ;
CHECK ( value [ " lie " ] . dump ( ) = = lie . dump ( ) ) ;
CHECK ( value [ " null " ] . dump ( ) = = null . dump ( ) ) ;
} // json::wvalue::wvalue(std::initializer_list<std::pair<std::string const, json::wvalue>>)
TEST_CASE ( " json::wvalue::wvalue(std::[unordered_]map<std::string, json::wvalue> const&) " )
{
json : : wvalue integer , number , truth , lie , null ;
integer = 2147483647 ;
number = 23.43 ;
truth = true ;
lie = false ;
json : : wvalue : : object map ( { { " integer " , integer } ,
{ " number " , number } ,
{ " truth " , truth } ,
{ " lie " , lie } ,
{ " null " , null } } ) ;
json : : wvalue value ( map ) ; /* copy-constructor. */
CHECK ( value [ " integer " ] . dump ( ) = = integer . dump ( ) ) ;
CHECK ( value [ " number " ] . dump ( ) = = number . dump ( ) ) ;
CHECK ( value [ " truth " ] . dump ( ) = = truth . dump ( ) ) ;
CHECK ( value [ " lie " ] . dump ( ) = = lie . dump ( ) ) ;
CHECK ( value [ " null " ] . dump ( ) = = null . dump ( ) ) ;
} // json::wvalue::wvalue(std::[unordered_]map<std::string, json::wvalue> const&)
TEST_CASE ( " json::wvalue::wvalue(std::[unordered_]map<std::string, json::wvalue>&&) " )
{
json : : wvalue integer , number , truth , lie , null ;
integer = 2147483647 ;
number = 23.43 ;
truth = true ;
lie = false ;
json : : wvalue : : object map = { { { " integer " , integer } ,
{ " number " , number } ,
{ " truth " , truth } ,
{ " lie " , lie } ,
{ " null " , null } } } ;
json : : wvalue value ( std : : move ( map ) ) ; /* move constructor. */
// json::wvalue value = std::move(map); /* move constructor. */
CHECK ( value [ " integer " ] . dump ( ) = = integer . dump ( ) ) ;
CHECK ( value [ " number " ] . dump ( ) = = number . dump ( ) ) ;
CHECK ( value [ " truth " ] . dump ( ) = = truth . dump ( ) ) ;
CHECK ( value [ " lie " ] . dump ( ) = = lie . dump ( ) ) ;
CHECK ( value [ " null " ] . dump ( ) = = null . dump ( ) ) ;
} // json::wvalue::wvalue(std::[unordered_]map<std::string, json::wvalue>&&)
TEST_CASE ( " json::wvalue::operator=(std::initializer_list<std::pair<std::string const, json::wvalue>>) " )
{
json : : wvalue integer , number , truth , lie , null ;
integer = 2147483647 ;
number = 23.43 ;
truth = true ;
lie = false ;
json : : wvalue value ;
/* initializer-list assignment. */
value = {
{ " integer " , integer } ,
{ " number " , number } ,
{ " truth " , truth } ,
{ " lie " , lie } ,
{ " null " , null } } ;
CHECK ( value [ " integer " ] . dump ( ) = = integer . dump ( ) ) ;
CHECK ( value [ " number " ] . dump ( ) = = number . dump ( ) ) ;
CHECK ( value [ " truth " ] . dump ( ) = = truth . dump ( ) ) ;
CHECK ( value [ " lie " ] . dump ( ) = = lie . dump ( ) ) ;
CHECK ( value [ " null " ] . dump ( ) = = null . dump ( ) ) ;
} // json::wvalue::operator=(std::initializer_list<std::pair<std::string const, json::wvalue>>)
TEST_CASE ( " json::wvalue::operator=(std::[unordered_]map<std::string, json::wvalue> const&) " )
{
json : : wvalue integer , number , truth , lie , null ;
integer = 2147483647 ;
number = 23.43 ;
truth = true ;
lie = false ;
json : : wvalue : : object map ( { { " integer " , integer } ,
{ " number " , number } ,
{ " truth " , truth } ,
{ " lie " , lie } ,
{ " null " , null } } ) ;
json : : wvalue value ;
value = map ; /* copy assignment. */
CHECK ( value [ " integer " ] . dump ( ) = = integer . dump ( ) ) ;
CHECK ( value [ " number " ] . dump ( ) = = number . dump ( ) ) ;
CHECK ( value [ " truth " ] . dump ( ) = = truth . dump ( ) ) ;
CHECK ( value [ " lie " ] . dump ( ) = = lie . dump ( ) ) ;
CHECK ( value [ " null " ] . dump ( ) = = null . dump ( ) ) ;
} // json::wvalue::operator=(std::[unordered_]map<std::string, json::wvalue> const&)
TEST_CASE ( " json::wvalue::operator=(std::[unordered_]map<std::string, json::wvalue>&&) " )
{
json : : wvalue integer , number , truth , lie , null ;
integer = 2147483647 ;
number = 23.43 ;
truth = true ;
lie = false ;
json : : wvalue : : object map ( { { " integer " , integer } ,
{ " number " , number } ,
{ " truth " , truth } ,
{ " lie " , lie } ,
{ " null " , null } } ) ;
json : : wvalue value ;
value = std : : move ( map ) ; /* move assignment. */
CHECK ( value [ " integer " ] . dump ( ) = = integer . dump ( ) ) ;
CHECK ( value [ " number " ] . dump ( ) = = number . dump ( ) ) ;
CHECK ( value [ " truth " ] . dump ( ) = = truth . dump ( ) ) ;
CHECK ( value [ " lie " ] . dump ( ) = = lie . dump ( ) ) ;
CHECK ( value [ " null " ] . dump ( ) = = null . dump ( ) ) ;
} // json::wvalue::operator=(std::[unordered_]map<std::string, json::wvalue>&&)
2021-08-06 16:37:18 +00:00
2021-05-12 12:45:55 +00:00
TEST_CASE ( " json_vector " )
2021-08-20 00:57:21 +00:00
{
2021-05-12 12:45:55 +00:00
json : : wvalue a ;
json : : wvalue b ;
json : : wvalue c ;
json : : wvalue d ;
json : : wvalue e ;
json : : wvalue f ;
json : : wvalue g ;
json : : wvalue h ;
a = 5 ;
b = 6 ;
c = 7 ;
d = 8 ;
e = 4 ;
f = 3 ;
g = 2 ;
h = 1 ;
std : : vector < json : : wvalue > nums ;
nums . emplace_back ( a ) ;
nums . emplace_back ( b ) ;
nums . emplace_back ( c ) ;
nums . emplace_back ( d ) ;
nums . emplace_back ( e ) ;
nums . emplace_back ( f ) ;
nums . emplace_back ( g ) ;
nums . emplace_back ( h ) ;
json : : wvalue x ( nums ) ;
CHECK ( 8 = = x . size ( ) ) ;
CHECK ( " [5,6,7,8,4,3,2,1] " = = x . dump ( ) ) ;
2021-11-25 11:45:38 +00:00
} // json_vector
2021-05-12 12:45:55 +00:00
2021-08-20 00:57:21 +00:00
TEST_CASE ( " json_list " )
{
2021-11-25 11:45:38 +00:00
json : : wvalue x ( json : : wvalue : : list ( { 5 , 6 , 7 , 8 , 4 , 3 , 2 , 1 } ) ) ;
2021-08-20 00:57:21 +00:00
CHECK ( 8 = = x . size ( ) ) ;
CHECK ( " [5,6,7,8,4,3,2,1] " = = x . dump ( ) ) ;
2021-11-25 11:45:38 +00:00
} // json_list
2021-08-20 00:57:21 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " template_basic " )
2014-07-30 15:50:38 +00:00
{
2021-11-25 11:45:38 +00:00
auto t = crow : : mustache : : compile ( R " ---(attack of {{name}})--- " ) ;
crow : : mustache : : context ctx ;
ctx [ " name " ] = " killer tomatoes " ;
2022-02-18 01:25:02 +00:00
auto result = t . render_string ( ctx ) ;
2021-11-25 11:45:38 +00:00
CHECK ( " attack of killer tomatoes " = = result ) ;
} // template_basic
2014-07-30 15:50:38 +00:00
2021-12-10 02:17:25 +00:00
TEST_CASE ( " template_function " )
{
2022-02-06 19:29:46 +00:00
auto t = crow : : mustache : : compile ( " attack of {{func}} " ) ;
crow : : mustache : : context ctx ;
ctx [ " name " ] = " killer tomatoes " ;
ctx [ " func " ] = [ & ] ( std : : string ) {
return std : : string ( " {{name}}, IN SPACE! " ) ;
} ;
2022-02-18 01:25:02 +00:00
auto result = t . render_string ( ctx ) ;
2022-02-06 19:29:46 +00:00
CHECK ( " attack of killer tomatoes, IN SPACE! " = = result ) ;
2021-12-10 02:17:25 +00:00
}
2020-10-18 16:59:15 +00:00
TEST_CASE ( " template_load " )
2014-08-02 01:46:00 +00:00
{
2021-11-25 11:45:38 +00:00
crow : : mustache : : set_base ( " . " ) ;
ofstream ( " test.mustache " ) < < R " ---(attack of {{name}})--- " ;
auto t = crow : : mustache : : load ( " test.mustache " ) ;
crow : : mustache : : context ctx ;
ctx [ " name " ] = " killer tomatoes " ;
2022-02-18 01:25:02 +00:00
auto result = t . render_string ( ctx ) ;
2021-11-25 11:45:38 +00:00
CHECK ( " attack of killer tomatoes " = = result ) ;
unlink ( " test.mustache " ) ;
} // template_load
2014-08-02 01:46:00 +00:00
2022-02-18 01:25:02 +00:00
TEST_CASE ( " TemplateRouting " )
{
SimpleApp app ;
CROW_ROUTE ( app , " /temp " )
( [ ] {
auto t = crow : : mustache : : compile ( R " ---(attack of {{name}})--- " ) ;
crow : : mustache : : context ctx ;
ctx [ " name " ] = " killer tomatoes " ;
return crow : : response ( t . render ( ctx ) ) ;
} ) ;
app . validate ( ) ;
{
request req ;
response res ;
req . url = " /temp " ;
app . handle ( req , res ) ;
CHECK ( " attack of killer tomatoes " = = res . body ) ;
CHECK ( " text/html " = = crow : : get_header_value ( res . headers , " Content-Type " ) ) ;
}
} // PathRouting
2020-10-18 16:59:15 +00:00
TEST_CASE ( " black_magic " )
2014-09-07 22:07:53 +00:00
{
2021-11-25 11:45:38 +00:00
using namespace black_magic ;
static_assert (
2020-10-19 08:02:57 +00:00
std : : is_same < void , last_element_type < int , char , void > : : type > : : value ,
" last_element_type " ) ;
2021-11-25 11:45:38 +00:00
static_assert ( std : : is_same < char , pop_back < int , char , void > : : rebind <
2020-10-19 08:02:57 +00:00
last_element_type > : : type > : : value ,
2021-11-25 11:45:38 +00:00
" pop_back " ) ;
static_assert (
2020-10-19 08:02:57 +00:00
std : : is_same < int , pop_back < int , char , void > : : rebind < pop_back > : : rebind <
2021-11-25 11:45:38 +00:00
last_element_type > : : type > : : value ,
2020-10-19 08:02:57 +00:00
" pop_back " ) ;
2021-11-25 11:45:38 +00:00
} // black_magic
2014-09-07 22:07:53 +00:00
2014-09-06 19:30:53 +00:00
struct NullMiddleware
{
2021-11-25 11:45:38 +00:00
struct context
2021-11-27 12:28:50 +00:00
{ } ;
2014-09-06 19:30:53 +00:00
2021-11-25 11:45:38 +00:00
template < typename AllContext >
void before_handle ( request & , response & , context & , AllContext & )
2021-11-27 12:28:50 +00:00
{ }
2014-09-06 19:30:53 +00:00
2021-11-25 11:45:38 +00:00
template < typename AllContext >
void after_handle ( request & , response & , context & , AllContext & )
2021-11-27 12:28:50 +00:00
{ }
2014-09-06 19:30:53 +00:00
} ;
2014-09-07 22:07:53 +00:00
struct NullSimpleMiddleware
{
2021-11-25 11:45:38 +00:00
struct context
2021-11-27 12:28:50 +00:00
{ } ;
2014-09-07 22:07:53 +00:00
2021-11-25 11:45:38 +00:00
void before_handle ( request & /*req*/ , response & /*res*/ , context & /*ctx*/ ) { }
2014-09-07 22:07:53 +00:00
2021-11-25 11:45:38 +00:00
void after_handle ( request & /*req*/ , response & /*res*/ , context & /*ctx*/ ) { }
2014-09-07 22:07:53 +00:00
} ;
2020-10-18 16:59:15 +00:00
TEST_CASE ( " middleware_simple " )
2014-09-06 19:30:53 +00:00
{
2021-11-25 11:45:38 +00:00
App < NullMiddleware , NullSimpleMiddleware > app ;
decltype ( app ) : : server_t server ( & app , LOCALHOST_ADDRESS , 45451 ) ;
CROW_ROUTE ( app , " / " )
2021-11-27 12:28:50 +00:00
( [ & ] ( const crow : : request & req ) {
2021-11-27 17:44:51 +00:00
app . get_context < NullMiddleware > ( req ) ;
app . get_context < NullSimpleMiddleware > ( req ) ;
return " " ;
} ) ;
2014-09-06 19:30:53 +00:00
}
struct IntSettingMiddleware
{
2021-11-25 11:45:38 +00:00
struct context
{
int val ;
} ;
template < typename AllContext >
void before_handle ( request & , response & , context & ctx , AllContext & )
{
ctx . val = 1 ;
}
template < typename AllContext >
void after_handle ( request & , response & , context & ctx , AllContext & )
{
ctx . val = 2 ;
}
2014-09-06 19:30:53 +00:00
} ;
2014-09-07 22:07:53 +00:00
std : : vector < std : : string > test_middleware_context_vector ;
struct FirstMW
{
2021-11-25 11:45:38 +00:00
struct context
{
std : : vector < string > v ;
} ;
void before_handle ( request & /*req*/ , response & /*res*/ , context & ctx )
{
ctx . v . push_back ( " 1 before " ) ;
}
void after_handle ( request & /*req*/ , response & /*res*/ , context & ctx )
{
ctx . v . push_back ( " 1 after " ) ;
test_middleware_context_vector = ctx . v ;
}
2014-09-07 22:07:53 +00:00
} ;
struct SecondMW
{
2021-11-25 11:45:38 +00:00
struct context
2021-11-27 12:28:50 +00:00
{ } ;
2021-11-25 11:45:38 +00:00
template < typename AllContext >
void before_handle ( request & req , response & res , context & , AllContext & all_ctx )
{
all_ctx . template get < FirstMW > ( ) . v . push_back ( " 2 before " ) ;
if ( req . url = = " /break " ) res . end ( ) ;
}
template < typename AllContext >
void after_handle ( request & , response & , context & , AllContext & all_ctx )
{
all_ctx . template get < FirstMW > ( ) . v . push_back ( " 2 after " ) ;
}
2014-09-07 22:07:53 +00:00
} ;
struct ThirdMW
{
2021-11-25 11:45:38 +00:00
struct context
2021-11-27 12:28:50 +00:00
{ } ;
2021-11-25 11:45:38 +00:00
template < typename AllContext >
void before_handle ( request & , response & , context & , AllContext & all_ctx )
{
all_ctx . template get < FirstMW > ( ) . v . push_back ( " 3 before " ) ;
}
template < typename AllContext >
void after_handle ( request & , response & , context & , AllContext & all_ctx )
{
all_ctx . template get < FirstMW > ( ) . v . push_back ( " 3 after " ) ;
}
2014-09-07 22:07:53 +00:00
} ;
2020-10-18 16:59:15 +00:00
TEST_CASE ( " middleware_context " )
2014-09-06 19:30:53 +00:00
{
2021-11-25 11:45:38 +00:00
static char buf [ 2048 ] ;
// SecondMW depends on FirstMW (it uses all_ctx.get<FirstMW>)
// so it leads to compile error if we remove FirstMW from definition
// App<IntSettingMiddleware, SecondMW> app;
// or change the order of FirstMW and SecondMW
// App<IntSettingMiddleware, SecondMW, FirstMW> app;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
App < IntSettingMiddleware , FirstMW , SecondMW , ThirdMW > app ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
int x { } ;
CROW_ROUTE ( app , " / " )
2021-11-27 12:28:50 +00:00
( [ & ] ( const request & req ) {
2021-11-27 17:44:51 +00:00
{
auto & ctx = app . get_context < IntSettingMiddleware > ( req ) ;
x = ctx . val ;
}
{
auto & ctx = app . get_context < FirstMW > ( req ) ;
ctx . v . push_back ( " handle " ) ;
}
2014-09-07 22:07:53 +00:00
2021-11-27 17:44:51 +00:00
return " " ;
} ) ;
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /break " )
2021-11-27 12:28:50 +00:00
( [ & ] ( const request & req ) {
2021-11-27 17:44:51 +00:00
{
auto & ctx = app . get_context < FirstMW > ( req ) ;
ctx . v . push_back ( " handle " ) ;
}
2020-10-19 08:02:57 +00:00
2021-11-27 17:44:51 +00:00
return " " ;
} ) ;
2020-10-19 08:02:57 +00:00
2022-03-10 12:44:39 +00:00
auto _ = app . bindaddr ( LOCALHOST_ADDRESS ) . port ( 45451 ) . run_async ( ) ;
2021-11-25 11:45:38 +00:00
app . wait_for_server_start ( ) ;
std : : string sendmsg = " GET / \r \n \r \n " ;
asio : : io_service is ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( sendmsg ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
}
{
auto & out = test_middleware_context_vector ;
CHECK ( 1 = = x ) ;
CHECK ( 7 = = out . size ( ) ) ;
CHECK ( " 1 before " = = out [ 0 ] ) ;
CHECK ( " 2 before " = = out [ 1 ] ) ;
CHECK ( " 3 before " = = out [ 2 ] ) ;
CHECK ( " handle " = = out [ 3 ] ) ;
CHECK ( " 3 after " = = out [ 4 ] ) ;
CHECK ( " 2 after " = = out [ 5 ] ) ;
CHECK ( " 1 after " = = out [ 6 ] ) ;
}
std : : string sendmsg2 = " GET /break \r \n \r \n " ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
c . send ( asio : : buffer ( sendmsg2 ) ) ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
}
{
auto & out = test_middleware_context_vector ;
CHECK ( 4 = = out . size ( ) ) ;
CHECK ( " 1 before " = = out [ 0 ] ) ;
CHECK ( " 2 before " = = out [ 1 ] ) ;
CHECK ( " 2 after " = = out [ 2 ] ) ;
CHECK ( " 1 after " = = out [ 3 ] ) ;
}
app . stop ( ) ;
} // middleware_context
2014-09-06 19:30:53 +00:00
2022-02-01 20:21:07 +00:00
struct LocalSecretMiddleware : crow : : ILocalMiddleware
{
2022-02-01 13:31:05 +00:00
struct context
{ } ;
void before_handle ( request & /*req*/ , response & res , context & /*ctx*/ )
{
res . code = 403 ;
res . end ( ) ;
}
void after_handle ( request & /*req*/ , response & /*res*/ , context & /*ctx*/ )
{ }
} ;
TEST_CASE ( " local_middleware " )
{
2022-02-08 18:57:33 +00:00
static char buf [ 2048 ] ;
2022-02-01 13:31:05 +00:00
App < LocalSecretMiddleware > app ;
CROW_ROUTE ( app , " / " )
( [ ] ( ) {
return " works! " ;
} ) ;
CROW_ROUTE ( app , " /secret " )
2022-02-01 20:21:07 +00:00
. middlewares < decltype ( app ) , LocalSecretMiddleware > ( ) ( [ ] ( ) {
return " works! " ;
} ) ;
2022-02-01 13:31:05 +00:00
app . validate ( ) ;
2022-03-10 12:44:39 +00:00
auto _ = app . bindaddr ( LOCALHOST_ADDRESS ) . port ( 45451 ) . run_async ( ) ;
2022-02-08 18:57:33 +00:00
app . wait_for_server_start ( ) ;
asio : : io_service is ;
2022-02-01 13:31:05 +00:00
{
2022-02-08 18:57:33 +00:00
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( " GET / \r \n \r \n " ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
CHECK ( std : : string ( buf ) . find ( " 200 " ) ! = std : : string : : npos ) ;
2022-02-01 13:31:05 +00:00
}
{
2022-02-08 18:57:33 +00:00
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( " GET /secret \r \n \r \n " ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
CHECK ( std : : string ( buf ) . find ( " 403 " ) ! = std : : string : : npos ) ;
2022-02-01 13:31:05 +00:00
}
2022-02-08 18:57:33 +00:00
app . stop ( ) ;
2022-02-01 13:31:05 +00:00
} // local_middleware
2020-10-18 16:59:15 +00:00
TEST_CASE ( " middleware_cookieparser " )
2014-09-10 21:32:41 +00:00
{
2021-11-25 11:45:38 +00:00
static char buf [ 2048 ] ;
2014-09-10 21:32:41 +00:00
2021-11-25 11:45:38 +00:00
App < CookieParser > app ;
2014-09-10 21:32:41 +00:00
2021-11-25 11:45:38 +00:00
std : : string value1 ;
std : : string value2 ;
std : : string value3 ;
std : : string value4 ;
2014-09-10 21:32:41 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " / " )
2021-11-27 12:28:50 +00:00
( [ & ] ( const request & req ) {
2021-11-27 17:44:51 +00:00
{
auto & ctx = app . get_context < CookieParser > ( req ) ;
value1 = ctx . get_cookie ( " key1 " ) ;
value2 = ctx . get_cookie ( " key2 " ) ;
value3 = ctx . get_cookie ( " key3 " ) ;
value4 = ctx . get_cookie ( " key4 " ) ;
}
2014-09-13 23:16:49 +00:00
2021-11-27 17:44:51 +00:00
return " " ;
} ) ;
2020-10-19 08:02:57 +00:00
2022-03-10 12:44:39 +00:00
auto _ = app . bindaddr ( LOCALHOST_ADDRESS ) . port ( 45451 ) . run_async ( ) ;
2021-11-25 11:45:38 +00:00
app . wait_for_server_start ( ) ;
std : : string sendmsg =
2020-10-19 08:02:57 +00:00
" GET / \r \n Cookie: key1=value1; key2= \" val=ue2 \" ; key3= \" val \" ue3 \" ; "
" key4= \" val \" ue4 \" \r \n \r \n " ;
2021-11-25 11:45:38 +00:00
asio : : io_service is ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( sendmsg ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
}
{
CHECK ( " value1 " = = value1 ) ;
CHECK ( " val=ue2 " = = value2 ) ;
CHECK ( " val \" ue3 " = = value3 ) ;
CHECK ( " val \" ue4 " = = value4 ) ;
}
app . stop ( ) ;
} // middleware_cookieparser
2014-09-13 23:16:49 +00:00
2022-02-22 14:38:51 +00:00
TEST_CASE ( " middleware_cors " )
{
static char buf [ 5012 ] ;
App < crow : : CORSHandler > app ;
auto & cors = app . get_middleware < crow : : CORSHandler > ( ) ;
2022-03-08 13:33:08 +00:00
// clang-format off
cors
. prefix ( " /origin " )
. origin ( " test.test " )
. prefix ( " /nocors " )
. ignore ( ) ;
// clang-format on
2022-02-22 14:38:51 +00:00
CROW_ROUTE ( app , " / " )
2022-03-08 13:33:08 +00:00
( [ & ] ( const request & ) {
2022-02-22 14:38:51 +00:00
return " - " ;
} ) ;
CROW_ROUTE ( app , " /origin " )
2022-03-08 13:33:08 +00:00
( [ & ] ( const request & ) {
return " - " ;
} ) ;
CROW_ROUTE ( app , " /nocors/path " )
( [ & ] ( const request & ) {
2022-02-22 14:38:51 +00:00
return " - " ;
} ) ;
auto _ = async ( launch : : async ,
[ & ] {
app . bindaddr ( LOCALHOST_ADDRESS ) . port ( 45451 ) . run ( ) ;
} ) ;
app . wait_for_server_start ( ) ;
asio : : io_service is ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( " GET / \r \n \r \n " ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
CHECK ( std : : string ( buf ) . find ( " Access-Control-Allow-Origin: * " ) ! = std : : string : : npos ) ;
}
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( " GET /origin \r \n \r \n " ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
CHECK ( std : : string ( buf ) . find ( " Access-Control-Allow-Origin: test.test " ) ! = std : : string : : npos ) ;
}
2022-03-08 13:33:08 +00:00
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( " GET /nocors/path \r \n \r \n " ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
CHECK ( std : : string ( buf ) . find ( " Access-Control-Allow-Origin: " ) = = std : : string : : npos ) ;
}
2022-02-22 14:38:51 +00:00
app . stop ( ) ;
} // middleware_cors
2020-10-19 08:02:57 +00:00
TEST_CASE ( " bug_quick_repeated_request " )
2014-10-14 08:48:35 +00:00
{
2021-11-25 11:45:38 +00:00
static char buf [ 2048 ] ;
2014-10-14 08:48:35 +00:00
2021-11-25 11:45:38 +00:00
SimpleApp app ;
2014-10-14 08:48:35 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " / " )
2021-11-27 17:44:51 +00:00
( [ & ] {
return " hello " ;
} ) ;
2014-10-14 08:48:35 +00:00
2022-03-10 12:44:39 +00:00
auto _ = app . bindaddr ( LOCALHOST_ADDRESS ) . port ( 45451 ) . run_async ( ) ;
2021-11-25 11:45:38 +00:00
app . wait_for_server_start ( ) ;
std : : string sendmsg = " GET / HTTP/1.1 \r \n Host: localhost \r \n \r \n " ;
asio : : io_service is ;
{
std : : vector < std : : future < void > > v ;
for ( int i = 0 ; i < 5 ; i + + )
{
2021-11-27 12:28:50 +00:00
v . push_back ( async ( launch : : async , [ & ] {
2021-11-27 17:44:51 +00:00
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
2014-10-14 08:48:35 +00:00
2021-11-27 17:44:51 +00:00
for ( int j = 0 ; j < 5 ; j + + )
{
c . send ( asio : : buffer ( sendmsg ) ) ;
2014-10-14 08:48:35 +00:00
2021-11-27 17:44:51 +00:00
size_t received = c . receive ( asio : : buffer ( buf , 2048 ) ) ;
CHECK ( " hello " = = std : : string ( buf + received - 5 , buf + received ) ) ;
}
c . close ( ) ;
} ) ) ;
2021-11-25 11:45:38 +00:00
}
2014-10-14 08:48:35 +00:00
}
2021-11-25 11:45:38 +00:00
app . stop ( ) ;
} // bug_quick_repeated_request
2016-03-19 15:05:48 +00:00
2020-10-19 08:02:57 +00:00
TEST_CASE ( " simple_url_params " )
{
2021-11-25 11:45:38 +00:00
static char buf [ 2048 ] ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
SimpleApp app ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
query_string last_url_params ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /params " )
2021-11-27 12:28:50 +00:00
( [ & last_url_params ] ( const crow : : request & req ) {
2021-11-27 17:44:51 +00:00
last_url_params = std : : move ( req . url_params ) ;
return " OK " ;
} ) ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
/// params?h=1&foo=bar&lol&count[]=1&count[]=4&pew=5.2
2020-10-19 08:02:57 +00:00
2022-03-10 12:44:39 +00:00
auto _ = app . bindaddr ( LOCALHOST_ADDRESS ) . port ( 45451 ) . run_async ( ) ;
2021-11-25 11:45:38 +00:00
app . wait_for_server_start ( ) ;
asio : : io_service is ;
std : : string sendmsg ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
// check empty params
sendmsg = " GET /params \r \n \r \n " ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( sendmsg ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
stringstream ss ;
ss < < last_url_params ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( " [ ] " = = ss . str ( ) ) ;
}
// check single presence
sendmsg = " GET /params?foobar \r \n \r \n " ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( sendmsg ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
2021-05-12 12:45:55 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( last_url_params . get ( " missing " ) = = nullptr ) ;
CHECK ( last_url_params . get ( " foobar " ) ! = nullptr ) ;
CHECK ( last_url_params . get_list ( " missing " ) . empty ( ) ) ;
}
// check multiple presence
sendmsg = " GET /params?foo&bar&baz \r \n \r \n " ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( sendmsg ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
CHECK ( last_url_params . get ( " missing " ) = = nullptr ) ;
CHECK ( last_url_params . get ( " foo " ) ! = nullptr ) ;
CHECK ( last_url_params . get ( " bar " ) ! = nullptr ) ;
CHECK ( last_url_params . get ( " baz " ) ! = nullptr ) ;
}
// check single value
sendmsg = " GET /params?hello=world \r \n \r \n " ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( sendmsg ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
CHECK ( string ( last_url_params . get ( " hello " ) ) = = " world " ) ;
}
// check multiple value
sendmsg = " GET /params?hello=world&left=right&up=down \r \n \r \n " ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( sendmsg ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
query_string mutable_params ( last_url_params ) ;
CHECK ( string ( mutable_params . get ( " hello " ) ) = = " world " ) ;
CHECK ( string ( mutable_params . get ( " left " ) ) = = " right " ) ;
CHECK ( string ( mutable_params . get ( " up " ) ) = = " down " ) ;
std : : string z = mutable_params . pop ( " left " ) ;
CHECK ( z = = " right " ) ;
CHECK ( mutable_params . get ( " left " ) = = nullptr ) ;
}
// check multiple value, multiple types
sendmsg = " GET /params?int=100&double=123.45&boolean=1 \r \n \r \n " ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( sendmsg ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
CHECK ( boost : : lexical_cast < int > ( last_url_params . get ( " int " ) ) = = 100 ) ;
CHECK ( boost : : lexical_cast < double > ( last_url_params . get ( " double " ) ) = =
123.45 ) ;
CHECK ( boost : : lexical_cast < bool > ( last_url_params . get ( " boolean " ) ) ) ;
}
// check single array value
sendmsg = " GET /params?tmnt[]=leonardo \r \n \r \n " ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( sendmsg ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
CHECK ( last_url_params . get ( " tmnt " ) = = nullptr ) ;
CHECK ( last_url_params . get_list ( " tmnt " ) . size ( ) = = 1 ) ;
CHECK ( string ( last_url_params . get_list ( " tmnt " ) [ 0 ] ) = = " leonardo " ) ;
}
// check multiple array value
sendmsg = " GET /params?tmnt[]=leonardo&tmnt[]=donatello&tmnt[]=raphael \r \n \r \n " ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( sendmsg ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
CHECK ( last_url_params . get_list ( " tmnt " ) . size ( ) = = 3 ) ;
CHECK ( string ( last_url_params . get_list ( " tmnt " ) [ 0 ] ) = = " leonardo " ) ;
CHECK ( string ( last_url_params . get_list ( " tmnt " ) [ 1 ] ) = = " donatello " ) ;
CHECK ( string ( last_url_params . get_list ( " tmnt " ) [ 2 ] ) = = " raphael " ) ;
CHECK ( last_url_params . pop_list ( " tmnt " ) . size ( ) = = 3 ) ;
CHECK ( last_url_params . get_list ( " tmnt " ) . size ( ) = = 0 ) ;
}
// check dictionary value
sendmsg = " GET /params?kees[one]=vee1&kees[two]=vee2&kees[three]=vee3 \r \n \r \n " ;
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint ( asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( sendmsg ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
c . close ( ) ;
CHECK ( last_url_params . get_dict ( " kees " ) . size ( ) = = 3 ) ;
CHECK ( string ( last_url_params . get_dict ( " kees " ) [ " one " ] ) = = " vee1 " ) ;
CHECK ( string ( last_url_params . get_dict ( " kees " ) [ " two " ] ) = = " vee2 " ) ;
CHECK ( string ( last_url_params . get_dict ( " kees " ) [ " three " ] ) = = " vee3 " ) ;
CHECK ( last_url_params . pop_dict ( " kees " ) . size ( ) = = 3 ) ;
CHECK ( last_url_params . get_dict ( " kees " ) . size ( ) = = 0 ) ;
}
app . stop ( ) ;
} // simple_url_params
2014-10-14 08:48:35 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " route_dynamic " )
2015-02-18 15:57:01 +00:00
{
2021-11-25 11:45:38 +00:00
SimpleApp app ;
int x = 1 ;
2021-11-27 12:28:50 +00:00
app . route_dynamic ( " / " ) ( [ & ] {
2021-11-27 17:44:51 +00:00
x = 2 ;
return " " ;
} ) ;
2020-10-19 08:02:57 +00:00
2021-11-27 12:28:50 +00:00
app . route_dynamic ( " /set4 " ) ( [ & ] ( const request & ) {
2021-11-27 17:44:51 +00:00
x = 4 ;
return " " ;
} ) ;
2021-11-27 12:28:50 +00:00
app . route_dynamic ( " /set5 " ) ( [ & ] ( const request & , response & res ) {
2021-11-27 17:44:51 +00:00
x = 5 ;
res . end ( ) ;
} ) ;
2020-10-19 08:02:57 +00:00
2021-11-27 12:28:50 +00:00
app . route_dynamic ( " /set_int/<int> " ) ( [ & ] ( int y ) {
2021-11-27 17:44:51 +00:00
x = y ;
return " " ;
} ) ;
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
try
{
2021-11-27 17:44:51 +00:00
app . route_dynamic ( " /invalid_test/<double>/<path> " ) ( [ ] ( ) {
return " " ;
} ) ;
2021-11-25 11:45:38 +00:00
FAIL_CHECK ( ) ;
}
catch ( std : : exception & )
2021-11-27 12:28:50 +00:00
{ }
2020-10-19 08:02:57 +00:00
2021-11-25 11:45:38 +00:00
// app is in an invalid state when route_dynamic throws an exception.
try
{
app . validate ( ) ;
FAIL_CHECK ( ) ;
}
catch ( std : : exception & )
2021-11-27 12:28:50 +00:00
{ }
2015-02-19 03:16:28 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
req . url = " / " ;
app . handle ( req , res ) ;
CHECK ( x = = 2 ) ;
}
{
request req ;
response res ;
req . url = " /set_int/42 " ;
app . handle ( req , res ) ;
CHECK ( x = = 42 ) ;
}
{
request req ;
response res ;
req . url = " /set5 " ;
app . handle ( req , res ) ;
CHECK ( x = = 5 ) ;
}
{
request req ;
response res ;
req . url = " /set4 " ;
app . handle ( req , res ) ;
CHECK ( x = = 4 ) ;
}
} // route_dynamic
2015-02-18 15:57:01 +00:00
2020-10-31 00:05:24 +00:00
TEST_CASE ( " multipart " )
{
2022-03-10 12:44:39 +00:00
//
//--CROW-BOUNDARY
//Content-Disposition: form-data; name=\"hello\"
//
//world
//--CROW-BOUNDARY
//Content-Disposition: form-data; name=\"world\"
//
//hello
//--CROW-BOUNDARY
//Content-Disposition: form-data; name=\"multiline\"
//
//text
//text
//text
//--CROW-BOUNDARY--
//
2021-11-25 11:45:38 +00:00
std : : string test_string = " --CROW-BOUNDARY \r \n Content-Disposition: form-data; name= \" hello \" \r \n \r \n world \r \n --CROW-BOUNDARY \r \n Content-Disposition: form-data; name= \" world \" \r \n \r \n hello \r \n --CROW-BOUNDARY \r \n Content-Disposition: form-data; name= \" multiline \" \r \n \r \n text \n text \n text \r \n --CROW-BOUNDARY-- \r \n " ;
2020-10-31 00:05:24 +00:00
2021-11-25 11:45:38 +00:00
SimpleApp app ;
2020-10-31 00:05:24 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /multipart " )
2021-11-27 12:28:50 +00:00
( [ ] ( const crow : : request & req , crow : : response & res ) {
2021-11-27 17:44:51 +00:00
multipart : : message msg ( req ) ;
res . body = msg . dump ( ) ;
res . end ( ) ;
} ) ;
2020-10-31 00:05:24 +00:00
2021-11-25 11:45:38 +00:00
app . validate ( ) ;
2020-10-31 00:05:24 +00:00
2021-11-25 11:45:38 +00:00
{
request req ;
response res ;
2020-10-31 00:05:24 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /multipart " ;
req . add_header ( " Content-Type " , " multipart/form-data; boundary=CROW-BOUNDARY " ) ;
req . body = test_string ;
2020-10-31 00:05:24 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2020-10-31 00:05:24 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( test_string = = res . body ) ;
2022-03-10 12:44:39 +00:00
multipart : : message msg ( req ) ;
CHECK ( " hello " = = msg . get_part_by_name ( " world " ) . body ) ;
CHECK ( " form-data " = = msg . get_part_by_name ( " hello " ) . get_header_object ( " Content-Disposition " ) . value ) ;
}
// Check with `"` encapsulating the boundary (.NET clients do this)
{
request req ;
response res ;
req . url = " /multipart " ;
req . add_header ( " Content-Type " , " multipart/form-data; boundary= \" CROW-BOUNDARY \" " ) ;
req . body = test_string ;
app . handle ( req , res ) ;
CHECK ( test_string = = res . body ) ;
2021-11-25 11:45:38 +00:00
}
} // multipart
2020-10-31 00:05:24 +00:00
2020-10-18 16:59:15 +00:00
TEST_CASE ( " send_file " )
2020-10-12 21:52:15 +00:00
{
2020-10-31 00:05:24 +00:00
2021-11-25 11:45:38 +00:00
struct stat statbuf ;
stat ( " tests/img/cat.jpg " , & statbuf ) ;
2020-10-31 00:05:24 +00:00
2021-11-25 11:45:38 +00:00
SimpleApp app ;
2020-10-12 21:52:15 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /jpg " )
2021-11-27 12:28:50 +00:00
( [ ] ( const crow : : request & , crow : : response & res ) {
2021-11-27 17:44:51 +00:00
res . set_static_file_info ( " tests/img/cat.jpg " ) ;
res . end ( ) ;
} ) ;
2020-10-12 21:52:15 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /jpg2 " )
2021-11-27 12:28:50 +00:00
( [ ] ( const crow : : request & , crow : : response & res ) {
2021-11-27 17:44:51 +00:00
res . set_static_file_info (
" tests/img/cat2.jpg " ) ; // This file is nonexistent on purpose
res . end ( ) ;
} ) ;
2020-10-12 21:52:15 +00:00
2021-11-25 11:45:38 +00:00
app . validate ( ) ;
2020-10-26 23:41:29 +00:00
2021-11-25 11:45:38 +00:00
//File not found check
{
request req ;
response res ;
2020-10-26 23:41:29 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /jpg2 " ;
2020-10-26 23:41:29 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2020-10-26 23:41:29 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 404 = = res . code ) ;
}
2020-10-12 21:52:15 +00:00
2021-11-25 11:45:38 +00:00
//Headers check
{
request req ;
response res ;
2020-10-12 21:52:15 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /jpg " ;
2022-02-05 15:15:19 +00:00
req . http_ver_major = 1 ;
2020-10-12 21:52:15 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2020-10-12 21:52:15 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 200 = = res . code ) ;
CHECK ( " image/jpeg " = = res . headers . find ( " Content-Type " ) - > second ) ;
2022-02-05 15:15:19 +00:00
CHECK ( to_string ( statbuf . st_size ) = = res . headers . find ( " Content-Length " ) - > second ) ;
2021-11-25 11:45:38 +00:00
}
} // send_file
2020-10-21 01:02:09 +00:00
TEST_CASE ( " stream_response " )
{
SimpleApp app ;
2021-07-28 19:31:08 +00:00
2021-10-06 10:51:17 +00:00
const std : : string keyword_ = " hello " ;
const size_t repetitions = 250000 ;
2021-11-25 11:45:38 +00:00
const size_t key_response_size = keyword_ . length ( ) * repetitions ;
2021-10-06 10:51:17 +00:00
2021-07-28 19:31:08 +00:00
std : : string key_response ;
2021-10-06 10:32:35 +00:00
2021-11-25 11:45:38 +00:00
for ( size_t i = 0 ; i < repetitions ; i + + )
key_response + = keyword_ ;
2021-07-28 19:31:08 +00:00
2020-10-21 01:02:09 +00:00
CROW_ROUTE ( app , " /test " )
2021-11-27 12:28:50 +00:00
( [ & key_response ] ( const crow : : request & , crow : : response & res ) {
2021-11-27 17:44:51 +00:00
res . body = key_response ;
res . end ( ) ;
} ) ;
2020-10-21 01:02:09 +00:00
app . validate ( ) ;
2022-03-10 12:44:39 +00:00
// running the test on a separate thread to allow the client to sleep
2021-11-27 12:28:50 +00:00
std : : thread runTest ( [ & app , & key_response , key_response_size ] ( ) {
2022-03-10 12:44:39 +00:00
auto _ = app . bindaddr ( LOCALHOST_ADDRESS ) . port ( 45451 ) . run_async ( ) ;
2021-11-27 17:44:51 +00:00
app . wait_for_server_start ( ) ;
asio : : io_service is ;
std : : string sendmsg ;
2020-10-27 19:53:58 +00:00
2021-11-27 17:44:51 +00:00
//Total bytes received
unsigned int received = 0 ;
2022-02-05 15:15:19 +00:00
sendmsg = " GET /test HTTP/1.0 \r \n \r \n " ;
2021-11-27 17:44:51 +00:00
{
asio : : streambuf b ;
2020-10-31 00:05:24 +00:00
2021-11-27 17:44:51 +00:00
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
c . send ( asio : : buffer ( sendmsg ) ) ;
2021-10-06 10:32:35 +00:00
2021-11-27 17:44:51 +00:00
//consuming the headers, since we don't need those for the test
static char buf [ 2048 ] ;
size_t received_headers_bytes = 0 ;
2021-10-05 12:13:38 +00:00
2021-11-27 17:44:51 +00:00
// magic number is 102 (it's the size of the headers, which is how much this line below needs to read)
const size_t headers_bytes = 102 ;
while ( received_headers_bytes < headers_bytes )
received_headers_bytes + = c . receive ( asio : : buffer ( buf , 2048 ) ) ;
received + = received_headers_bytes - headers_bytes ; //add any extra that might have been received to the proper received count
2020-10-27 19:53:58 +00:00
2021-10-05 12:13:38 +00:00
2021-11-27 17:44:51 +00:00
while ( received < key_response_size )
{
asio : : streambuf : : mutable_buffers_type bufs = b . prepare ( 16384 ) ;
2021-10-05 12:13:38 +00:00
2021-11-27 17:44:51 +00:00
size_t n = c . receive ( bufs ) ;
b . commit ( n ) ;
received + = n ;
2020-10-27 19:53:58 +00:00
2021-11-27 17:44:51 +00:00
std : : istream is ( & b ) ;
std : : string s ;
is > > s ;
2020-10-21 01:02:09 +00:00
2021-11-27 17:44:51 +00:00
CHECK ( key_response . substr ( received - n , n ) = = s ) ;
2020-10-31 00:05:24 +00:00
2022-02-05 15:15:19 +00:00
//std::this_thread::sleep_for(std::chrono::milliseconds(20));
2021-11-27 17:44:51 +00:00
}
}
app . stop ( ) ;
} ) ;
2020-10-27 19:53:58 +00:00
runTest . join ( ) ;
2021-11-25 11:45:38 +00:00
} // stream_response
2020-11-09 01:47:41 +00:00
TEST_CASE ( " websocket " )
{
2021-11-25 11:45:38 +00:00
static std : : string http_message = " GET /ws HTTP/1.1 \r \n Connection: keep-alive, Upgrade \r \n upgrade: websocket \r \n Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ== \r \n Sec-WebSocket-Version: 13 \r \n \r \n " ;
2020-11-09 01:47:41 +00:00
2021-11-25 11:45:38 +00:00
static bool connected { false } ;
2020-11-09 01:47:41 +00:00
2021-11-25 11:45:38 +00:00
SimpleApp app ;
2020-11-09 01:47:41 +00:00
2021-11-27 12:28:50 +00:00
CROW_ROUTE ( app , " /ws " ) . websocket ( ) . onopen ( [ & ] ( websocket : : connection & ) {
2021-11-27 17:44:51 +00:00
connected = true ;
CROW_LOG_INFO < < " Connected websocket and value is " < < connected ;
} )
. onmessage ( [ & ] ( websocket : : connection & conn , const std : : string & message , bool isbin ) {
CROW_LOG_INFO < < " Message is \" " < < message < < ' \" ' ;
if ( ! isbin & & message = = " PINGME " )
conn . send_ping ( " " ) ;
else if ( ! isbin & & message = = " Hello " )
conn . send_text ( " Hello back " ) ;
else if ( isbin & & message = = " Hello bin " )
conn . send_binary ( " Hello back bin " ) ;
} )
. onclose ( [ & ] ( websocket : : connection & , const std : : string & ) {
CROW_LOG_INFO < < " Closing websocket " ;
} ) ;
2020-11-09 01:47:41 +00:00
2021-11-25 11:45:38 +00:00
app . validate ( ) ;
2020-11-09 01:47:41 +00:00
2022-03-10 12:44:39 +00:00
auto _ = app . bindaddr ( LOCALHOST_ADDRESS ) . port ( 45451 ) . run_async ( ) ;
2021-11-25 11:45:38 +00:00
app . wait_for_server_start ( ) ;
asio : : io_service is ;
2020-11-09 01:47:41 +00:00
2021-11-25 11:45:38 +00:00
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
2020-11-09 01:47:41 +00:00
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
2021-11-25 11:45:38 +00:00
char buf [ 2048 ] ;
//----------Handshake----------
{
std : : fill_n ( buf , 2048 , 0 ) ;
c . send ( asio : : buffer ( http_message ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 5 ) ) ;
CHECK ( connected ) ;
}
//----------Pong----------
{
std : : fill_n ( buf , 2048 , 0 ) ;
char ping_message [ 2 ] ( " \x89 " ) ;
c . send ( asio : : buffer ( ping_message , 2 ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 5 ) ) ;
CHECK ( ( int ) ( unsigned char ) buf [ 0 ] = = 0x8A ) ;
}
//----------Ping----------
{
std : : fill_n ( buf , 2048 , 0 ) ;
char not_ping_message [ 2 + 6 + 1 ] ( " \x81 \x06 "
" PINGME " ) ;
c . send ( asio : : buffer ( not_ping_message , 8 ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 5 ) ) ;
CHECK ( ( int ) ( unsigned char ) buf [ 0 ] = = 0x89 ) ;
}
//----------Text----------
{
std : : fill_n ( buf , 2048 , 0 ) ;
char text_message [ 2 + 5 + 1 ] ( " \x81 \x05 "
" Hello " ) ;
c . send ( asio : : buffer ( text_message , 7 ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 5 ) ) ;
std : : string checkstring ( std : : string ( buf ) . substr ( 0 , 12 ) ) ;
CHECK ( checkstring = = " \x81 \x0A Hello back " ) ;
}
//----------Binary----------
{
std : : fill_n ( buf , 2048 , 0 ) ;
char bin_message [ 2 + 9 + 1 ] ( " \x82 \x09 "
" Hello bin " ) ;
c . send ( asio : : buffer ( bin_message , 11 ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 5 ) ) ;
std : : string checkstring2 ( std : : string ( buf ) . substr ( 0 , 16 ) ) ;
CHECK ( checkstring2 = = " \x82 \x0E Hello back bin " ) ;
}
//----------Masked Text----------
{
std : : fill_n ( buf , 2048 , 0 ) ;
char text_masked_message [ 2 + 4 + 5 + 1 ] ( " \x81 \x85 "
" \x67 \xc6 \x69 \x73 "
" \x2f \xa3 \x05 \x1f \x08 " ) ;
c . send ( asio : : buffer ( text_masked_message , 11 ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 5 ) ) ;
std : : string checkstring3 ( std : : string ( buf ) . substr ( 0 , 12 ) ) ;
CHECK ( checkstring3 = = " \x81 \x0A Hello back " ) ;
}
//----------Masked Binary----------
{
std : : fill_n ( buf , 2048 , 0 ) ;
char bin_masked_message [ 2 + 4 + 9 + 1 ] ( " \x82 \x89 "
" \x67 \xc6 \x69 \x73 "
" \x2f \xa3 \x05 \x1f \x08 \xe6 \x0b \x1a \x09 " ) ;
c . send ( asio : : buffer ( bin_masked_message , 15 ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 5 ) ) ;
std : : string checkstring4 ( std : : string ( buf ) . substr ( 0 , 16 ) ) ;
CHECK ( checkstring4 = = " \x82 \x0E Hello back bin " ) ;
}
//----------16bit Length Text----------
{
std : : fill_n ( buf , 2048 , 0 ) ;
char b16_text_message [ 2 + 2 + 5 + 1 ] ( " \x81 \x7E "
" \x00 \x05 "
" Hello " ) ;
c . send ( asio : : buffer ( b16_text_message , 9 ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 5 ) ) ;
std : : string checkstring ( std : : string ( buf ) . substr ( 0 , 12 ) ) ;
CHECK ( checkstring = = " \x81 \x0A Hello back " ) ;
}
//----------64bit Length Text----------
{
std : : fill_n ( buf , 2048 , 0 ) ;
char b64text_message [ 2 + 8 + 5 + 1 ] ( " \x81 \x7F "
" \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x05 "
" Hello " ) ;
c . send ( asio : : buffer ( b64text_message , 15 ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 5 ) ) ;
std : : string checkstring ( std : : string ( buf ) . substr ( 0 , 12 ) ) ;
CHECK ( checkstring = = " \x81 \x0A Hello back " ) ;
}
//----------Close----------
{
std : : fill_n ( buf , 2048 , 0 ) ;
char close_message [ 10 ] ( " \x88 " ) ; //I do not know why, but the websocket code does not read this unless it's longer than 4 or so bytes
c . send ( asio : : buffer ( close_message , 10 ) ) ;
c . receive ( asio : : buffer ( buf , 2048 ) ) ;
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 5 ) ) ;
CHECK ( ( int ) ( unsigned char ) buf [ 0 ] = = 0x88 ) ;
}
app . stop ( ) ;
} // websocket
2021-01-02 19:12:04 +00:00
2021-08-30 00:25:30 +00:00
# ifdef CROW_ENABLE_COMPRESSION
2021-01-02 19:12:04 +00:00
TEST_CASE ( " zlib_compression " )
{
static char buf_deflate [ 2048 ] ;
static char buf_gzip [ 2048 ] ;
SimpleApp app_deflate , app_gzip ;
std : : string expected_string = " Although moreover mistaken kindness me feelings do be marianne. Son over own nay with tell they cold upon are. "
" Cordial village and settled she ability law herself. Finished why bringing but sir bachelor unpacked any thoughts. "
" Unpleasing unsatiable particular inquietude did nor sir. Get his declared appetite distance his together now families. "
" Friends am himself at on norland it viewing. Suspected elsewhere you belonging continued commanded she. " ;
// test deflate
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app_deflate , " /test_compress " )
2021-11-27 17:44:51 +00:00
( [ & ] ( ) {
return expected_string ;
} ) ;
2021-01-02 19:12:04 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app_deflate , " /test " )
2021-11-27 12:28:50 +00:00
( [ & ] ( const request & , response & res ) {
2021-01-02 19:12:04 +00:00
res . compressed = false ;
res . body = expected_string ;
2021-11-27 17:44:51 +00:00
res . end ( ) ;
} ) ;
2021-01-02 19:12:04 +00:00
// test gzip
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app_gzip , " /test_compress " )
2021-11-27 17:44:51 +00:00
( [ & ] ( ) {
return expected_string ;
} ) ;
2021-01-02 19:12:04 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app_gzip , " /test " )
2021-11-27 12:28:50 +00:00
( [ & ] ( const request & , response & res ) {
2021-01-02 19:12:04 +00:00
res . compressed = false ;
res . body = expected_string ;
2021-11-27 17:44:51 +00:00
res . end ( ) ;
} ) ;
2021-01-02 19:12:04 +00:00
2022-03-10 12:44:39 +00:00
auto t1 = app_deflate . bindaddr ( LOCALHOST_ADDRESS ) . port ( 45451 ) . use_compression ( compression : : algorithm : : DEFLATE ) . run_async ( ) ;
2022-03-16 15:45:31 +00:00
auto t2 = app_gzip . bindaddr ( LOCALHOST_ADDRESS ) . port ( 45452 ) . use_compression ( compression : : algorithm : : GZIP ) . run_async ( ) ;
2021-01-02 19:12:04 +00:00
app_deflate . wait_for_server_start ( ) ;
app_gzip . wait_for_server_start ( ) ;
std : : string test_compress_msg = " GET /test_compress \r \n Accept-Encoding: gzip, deflate \r \n \r \n " ;
std : : string test_compress_no_header_msg = " GET /test_compress \r \n \r \n " ;
std : : string test_none_msg = " GET /test \r \n \r \n " ;
2021-11-27 12:28:50 +00:00
auto inflate_string = [ ] ( std : : string const & deflated_string ) - > const std : : string {
2021-01-02 19:12:04 +00:00
std : : string inflated_string ;
Bytef tmp [ 8192 ] ;
z_stream zstream { } ;
zstream . avail_in = deflated_string . size ( ) ;
// Nasty const_cast but zlib won't alter its contents
2021-11-25 11:45:38 +00:00
zstream . next_in = const_cast < Bytef * > ( reinterpret_cast < Bytef const * > ( deflated_string . c_str ( ) ) ) ;
2021-01-02 19:12:04 +00:00
// Initialize with automatic header detection, for gzip support
if ( : : inflateInit2 ( & zstream , MAX_WBITS | 32 ) = = Z_OK )
{
do
{
zstream . avail_out = sizeof ( tmp ) ;
zstream . next_out = & tmp [ 0 ] ;
auto ret = : : inflate ( & zstream , Z_NO_FLUSH ) ;
if ( ret = = Z_OK | | ret = = Z_STREAM_END )
{
std : : copy ( & tmp [ 0 ] , & tmp [ sizeof ( tmp ) - zstream . avail_out ] , std : : back_inserter ( inflated_string ) ) ;
}
else
{
// Something went wrong with inflate; make sure we return an empty string
inflated_string . clear ( ) ;
break ;
}
} while ( zstream . avail_out = = 0 ) ;
// Free zlib's internal memory
: : inflateEnd ( & zstream ) ;
}
return inflated_string ;
} ;
asio : : io_service is ;
{
2022-02-06 18:01:22 +00:00
// Compression
{
asio : : ip : : tcp : : socket socket [ 2 ] = { asio : : ip : : tcp : : socket ( is ) , asio : : ip : : tcp : : socket ( is ) } ;
socket [ 0 ] . connect ( asio : : ip : : tcp : : endpoint ( asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
socket [ 1 ] . connect ( asio : : ip : : tcp : : endpoint ( asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45452 ) ) ;
2021-01-02 19:12:04 +00:00
2022-02-06 18:01:22 +00:00
socket [ 0 ] . send ( asio : : buffer ( test_compress_msg ) ) ;
socket [ 1 ] . send ( asio : : buffer ( test_compress_msg ) ) ;
2021-01-02 19:12:04 +00:00
2022-02-06 18:01:22 +00:00
socket [ 0 ] . receive ( asio : : buffer ( buf_deflate , 2048 ) ) ;
socket [ 1 ] . receive ( asio : : buffer ( buf_gzip , 2048 ) ) ;
2021-01-02 19:12:04 +00:00
2022-02-06 18:01:22 +00:00
std : : string response_deflate ;
std : : string response_gzip ;
2021-01-02 19:12:04 +00:00
2022-02-06 19:29:46 +00:00
for ( unsigned i { 0 } ; i < 2048 ; i + + )
2022-02-06 18:01:22 +00:00
{
if ( buf_deflate [ i ] = = 0 )
{
bool end = true ;
2022-02-06 19:29:46 +00:00
for ( unsigned j = i ; j < 2048 ; j + + )
2022-02-06 18:01:22 +00:00
{
2022-02-06 19:29:46 +00:00
if ( buf_deflate [ j ] ! = 0 )
2022-02-06 18:01:22 +00:00
{
end = false ;
break ;
}
}
if ( end )
{
response_deflate . push_back ( 0 ) ;
response_deflate . push_back ( 0 ) ;
break ;
}
}
response_deflate . push_back ( buf_deflate [ i ] ) ;
}
2021-01-02 19:12:04 +00:00
2022-02-06 19:29:46 +00:00
for ( unsigned i { 0 } ; i < 2048 ; i + + )
2022-02-06 18:01:22 +00:00
{
if ( buf_gzip [ i ] = = 0 )
{
bool end = true ;
2022-02-06 19:29:46 +00:00
for ( unsigned j = i ; j < 2048 ; j + + )
2022-02-06 18:01:22 +00:00
{
2022-02-06 19:29:46 +00:00
if ( buf_gzip [ j ] ! = 0 )
2022-02-06 18:01:22 +00:00
{
end = false ;
break ;
}
}
if ( end )
{
response_deflate . push_back ( 0 ) ;
response_deflate . push_back ( 0 ) ;
break ;
}
}
response_gzip . push_back ( buf_gzip [ i ] ) ;
}
2021-01-02 19:12:04 +00:00
2022-02-06 19:29:46 +00:00
response_deflate = inflate_string ( response_deflate . substr ( response_deflate . find ( " \r \n \r \n " ) + 4 ) ) ;
response_gzip = inflate_string ( response_gzip . substr ( response_gzip . find ( " \r \n \r \n " ) + 4 ) ) ;
2021-01-02 19:12:04 +00:00
2022-02-06 18:01:22 +00:00
socket [ 0 ] . close ( ) ;
socket [ 1 ] . close ( ) ;
CHECK ( expected_string = = response_deflate ) ;
CHECK ( expected_string = = response_gzip ) ;
}
// No Header (thus no compression)
{
asio : : ip : : tcp : : socket socket [ 2 ] = { asio : : ip : : tcp : : socket ( is ) , asio : : ip : : tcp : : socket ( is ) } ;
socket [ 0 ] . connect ( asio : : ip : : tcp : : endpoint ( asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
socket [ 1 ] . connect ( asio : : ip : : tcp : : endpoint ( asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45452 ) ) ;
2021-01-02 19:12:04 +00:00
2022-02-06 18:01:22 +00:00
socket [ 0 ] . send ( asio : : buffer ( test_compress_no_header_msg ) ) ;
socket [ 1 ] . send ( asio : : buffer ( test_compress_no_header_msg ) ) ;
2021-01-02 19:12:04 +00:00
2022-02-06 18:01:22 +00:00
socket [ 0 ] . receive ( asio : : buffer ( buf_deflate , 2048 ) ) ;
socket [ 1 ] . receive ( asio : : buffer ( buf_gzip , 2048 ) ) ;
2021-01-02 19:12:04 +00:00
2022-02-06 18:01:22 +00:00
std : : string response_deflate ( buf_deflate ) ;
std : : string response_gzip ( buf_gzip ) ;
response_deflate = response_deflate . substr ( 98 ) ;
response_gzip = response_gzip . substr ( 98 ) ;
2021-01-02 19:12:04 +00:00
2022-02-06 18:01:22 +00:00
socket [ 0 ] . close ( ) ;
socket [ 1 ] . close ( ) ;
CHECK ( expected_string = = response_deflate ) ;
CHECK ( expected_string = = response_gzip ) ;
}
// No compression
{
asio : : ip : : tcp : : socket socket [ 2 ] = { asio : : ip : : tcp : : socket ( is ) , asio : : ip : : tcp : : socket ( is ) } ;
socket [ 0 ] . connect ( asio : : ip : : tcp : : endpoint ( asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
socket [ 1 ] . connect ( asio : : ip : : tcp : : endpoint ( asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45452 ) ) ;
2021-01-02 19:12:04 +00:00
2022-02-06 18:01:22 +00:00
socket [ 0 ] . send ( asio : : buffer ( test_none_msg ) ) ;
socket [ 1 ] . send ( asio : : buffer ( test_none_msg ) ) ;
2021-01-02 19:12:04 +00:00
2022-02-06 18:01:22 +00:00
socket [ 0 ] . receive ( asio : : buffer ( buf_deflate , 2048 ) ) ;
socket [ 1 ] . receive ( asio : : buffer ( buf_gzip , 2048 ) ) ;
2021-01-02 19:12:04 +00:00
2022-02-06 18:01:22 +00:00
std : : string response_deflate ( buf_deflate ) ;
std : : string response_gzip ( buf_gzip ) ;
response_deflate = response_deflate . substr ( 98 ) ;
response_gzip = response_gzip . substr ( 98 ) ;
2021-01-02 19:12:04 +00:00
2022-02-06 18:01:22 +00:00
socket [ 0 ] . close ( ) ;
socket [ 1 ] . close ( ) ;
CHECK ( expected_string = = response_deflate ) ;
CHECK ( expected_string = = response_gzip ) ;
}
}
2021-11-25 11:45:38 +00:00
2022-02-06 18:01:22 +00:00
app_deflate . stop ( ) ;
app_gzip . stop ( ) ;
2021-11-25 11:45:38 +00:00
} // zlib_compression
2021-08-30 00:25:30 +00:00
# endif
2021-04-12 05:25:09 +00:00
TEST_CASE ( " catchall " )
{
SimpleApp app ;
SimpleApp app2 ;
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " /place " )
2021-11-27 17:44:51 +00:00
( [ ] ( ) {
return " place " ;
} ) ;
2021-04-12 05:25:09 +00:00
2021-11-25 11:45:38 +00:00
CROW_CATCHALL_ROUTE ( app )
2021-11-27 17:44:51 +00:00
( [ ] ( response & res ) {
res . body = " !place " ;
} ) ;
2021-04-12 05:25:09 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app2 , " /place " )
2021-11-27 17:44:51 +00:00
( [ ] ( ) {
return " place " ;
} ) ;
2021-04-12 05:25:09 +00:00
app . validate ( ) ;
app2 . validate ( ) ;
{
2021-11-25 11:45:38 +00:00
request req ;
response res ;
2021-04-12 05:25:09 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /place " ;
2021-04-12 05:25:09 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2021-04-12 05:25:09 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 200 = = res . code ) ;
2021-04-12 05:25:09 +00:00
}
{
2021-11-25 11:45:38 +00:00
request req ;
response res ;
2021-04-12 05:25:09 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /another_place " ;
2021-04-12 05:25:09 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2021-04-12 05:25:09 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 404 = = res . code ) ;
CHECK ( " !place " = = res . body ) ;
2021-04-12 05:25:09 +00:00
}
{
2021-11-25 11:45:38 +00:00
request req ;
response res ;
2021-04-12 05:25:09 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /place " ;
2021-04-12 05:25:09 +00:00
2021-11-25 11:45:38 +00:00
app2 . handle ( req , res ) ;
2021-04-12 05:25:09 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 200 = = res . code ) ;
2021-04-12 05:25:09 +00:00
}
{
2021-11-25 11:45:38 +00:00
request req ;
response res ;
2021-04-12 05:25:09 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /another_place " ;
2021-04-12 05:25:09 +00:00
2021-11-25 11:45:38 +00:00
app2 . handle ( req , res ) ;
2021-04-12 05:25:09 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 404 = = res . code ) ;
2021-04-12 05:25:09 +00:00
}
2021-11-25 11:45:38 +00:00
} // catchall
2021-07-28 19:31:08 +00:00
TEST_CASE ( " blueprint " )
{
SimpleApp app ;
crow : : Blueprint bp ( " bp_prefix " , " cstat " , " ctemplate " ) ;
crow : : Blueprint bp_not_sub ( " bp_prefix_second " ) ;
crow : : Blueprint sub_bp ( " bp2 " , " csstat " , " cstemplate " ) ;
crow : : Blueprint sub_sub_bp ( " bp3 " ) ;
CROW_BP_ROUTE ( sub_bp , " /hello " )
2021-11-27 17:44:51 +00:00
( [ ] ( ) {
return " Hello world! " ;
} ) ;
2021-07-28 19:31:08 +00:00
CROW_BP_ROUTE ( bp_not_sub , " /hello " )
2021-11-27 17:44:51 +00:00
( [ ] ( ) {
return " Hello world! " ;
} ) ;
2021-07-28 19:31:08 +00:00
CROW_BP_ROUTE ( sub_sub_bp , " /hi " )
2021-11-27 17:44:51 +00:00
( [ ] ( ) {
return " Hi world! " ;
} ) ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
CROW_BP_CATCHALL_ROUTE ( sub_bp )
2021-11-27 17:44:51 +00:00
( [ ] ( ) {
return response ( 200 , " WRONG!! " ) ;
} ) ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
app . register_blueprint ( bp ) ;
app . register_blueprint ( bp_not_sub ) ;
bp . register_blueprint ( sub_bp ) ;
2021-07-28 19:31:08 +00:00
sub_bp . register_blueprint ( sub_sub_bp ) ;
app . validate ( ) ;
{
2021-11-25 11:45:38 +00:00
request req ;
response res ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /bp_prefix/bp2/hello " ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( " Hello world! " = = res . body ) ;
2021-07-28 19:31:08 +00:00
}
{
2021-11-25 11:45:38 +00:00
request req ;
response res ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /bp_prefix_second/hello " ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( " Hello world! " = = res . body ) ;
2021-07-28 19:31:08 +00:00
}
{
2021-11-25 11:45:38 +00:00
request req ;
response res ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /bp_prefix/bp2/bp3/hi " ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( " Hi world! " = = res . body ) ;
2021-07-28 19:31:08 +00:00
}
{
2021-11-25 11:45:38 +00:00
request req ;
response res ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /bp_prefix/nonexistent " ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 404 = = res . code ) ;
2021-07-28 19:31:08 +00:00
}
{
2021-11-25 11:45:38 +00:00
request req ;
response res ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /bp_prefix_second/nonexistent " ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 404 = = res . code ) ;
2021-07-28 19:31:08 +00:00
}
{
2021-11-25 11:45:38 +00:00
request req ;
response res ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /bp_prefix/bp2/nonexistent " ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 200 = = res . code ) ;
CHECK ( " WRONG!! " = = res . body ) ;
2021-07-28 19:31:08 +00:00
}
{
2021-11-25 11:45:38 +00:00
request req ;
response res ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
req . url = " /bp_prefix/bp2/bp3/nonexistent " ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
app . handle ( req , res ) ;
2021-07-28 19:31:08 +00:00
2021-11-25 11:45:38 +00:00
CHECK ( 200 = = res . code ) ;
CHECK ( " WRONG!! " = = res . body ) ;
2021-07-28 19:31:08 +00:00
}
2021-11-25 11:45:38 +00:00
} // blueprint
2021-10-30 23:50:19 +00:00
TEST_CASE ( " base64 " )
{
2021-11-25 11:45:38 +00:00
unsigned char sample_bin [ ] = { 0x14 , 0xfb , 0x9c , 0x03 , 0xd9 , 0x7e } ;
std : : string sample_bin_enc = " FPucA9l+ " ;
std : : string sample_bin_enc_url = " FPucA9l- " ;
unsigned char sample_bin1 [ ] = { 0x14 , 0xfb , 0x9c , 0x03 , 0xd9 } ;
std : : string sample_bin1_enc = " FPucA9k= " ;
std : : string sample_bin1_enc_np = " FPucA9k " ;
unsigned char sample_bin2 [ ] = { 0x14 , 0xfb , 0x9c , 0x03 } ;
std : : string sample_bin2_enc = " FPucAw== " ;
std : : string sample_bin2_enc_np = " FPucAw " ;
std : : string sample_text = " Crow Allows users to handle requests that may not come from the network. This is done by calling the handle(req, res) method and providing a request and response objects. Which causes crow to identify and run the appropriate handler, returning the resulting response. " ;
std : : string sample_base64 = " Q3JvdyBBbGxvd3MgdXNlcnMgdG8gaGFuZGxlIHJlcXVlc3RzIHRoYXQgbWF5IG5vdCBjb21lIGZyb20gdGhlIG5ldHdvcmsuIFRoaXMgaXMgZG9uZSBieSBjYWxsaW5nIHRoZSBoYW5kbGUocmVxLCByZXMpIG1ldGhvZCBhbmQgcHJvdmlkaW5nIGEgcmVxdWVzdCBhbmQgcmVzcG9uc2Ugb2JqZWN0cy4gV2hpY2ggY2F1c2VzIGNyb3cgdG8gaWRlbnRpZnkgYW5kIHJ1biB0aGUgYXBwcm9wcmlhdGUgaGFuZGxlciwgcmV0dXJuaW5nIHRoZSByZXN1bHRpbmcgcmVzcG9uc2Uu " ;
CHECK ( crow : : utility : : base64encode ( sample_text , sample_text . length ( ) ) = = sample_base64 ) ;
CHECK ( crow : : utility : : base64encode ( ( unsigned char * ) sample_bin , 6 ) = = sample_bin_enc ) ;
2021-10-30 23:50:19 +00:00
CHECK ( crow : : utility : : base64encode_urlsafe ( ( unsigned char * ) sample_bin , 6 ) = = sample_bin_enc_url ) ;
2021-11-25 11:45:38 +00:00
CHECK ( crow : : utility : : base64encode ( ( unsigned char * ) sample_bin1 , 5 ) = = sample_bin1_enc ) ;
CHECK ( crow : : utility : : base64encode ( ( unsigned char * ) sample_bin2 , 4 ) = = sample_bin2_enc ) ;
2021-10-30 23:50:19 +00:00
2022-01-23 17:31:22 +00:00
CHECK ( crow : : utility : : base64decode ( sample_base64 ) = = sample_text ) ;
2021-10-30 23:50:19 +00:00
CHECK ( crow : : utility : : base64decode ( sample_base64 , sample_base64 . length ( ) ) = = sample_text ) ;
CHECK ( crow : : utility : : base64decode ( sample_bin_enc , 8 ) = = std : : string ( reinterpret_cast < char const * > ( sample_bin ) ) ) ;
2022-01-23 17:31:22 +00:00
CHECK ( crow : : utility : : base64decode ( sample_bin_enc_url , 8 ) = = std : : string ( reinterpret_cast < char const * > ( sample_bin ) ) ) ;
2021-11-25 11:45:38 +00:00
CHECK ( crow : : utility : : base64decode ( sample_bin1_enc , 8 ) = = std : : string ( reinterpret_cast < char const * > ( sample_bin1 ) ) . substr ( 0 , 5 ) ) ;
CHECK ( crow : : utility : : base64decode ( sample_bin1_enc_np , 7 ) = = std : : string ( reinterpret_cast < char const * > ( sample_bin1 ) ) . substr ( 0 , 5 ) ) ;
CHECK ( crow : : utility : : base64decode ( sample_bin2_enc , 8 ) = = std : : string ( reinterpret_cast < char const * > ( sample_bin2 ) ) . substr ( 0 , 4 ) ) ;
CHECK ( crow : : utility : : base64decode ( sample_bin2_enc_np , 6 ) = = std : : string ( reinterpret_cast < char const * > ( sample_bin2 ) ) . substr ( 0 , 4 ) ) ;
} // base64
2021-11-14 12:04:19 +00:00
2022-01-22 15:40:26 +00:00
TEST_CASE ( " sanitize_filename " )
{
auto sanitize_filename = [ ] ( string s ) {
crow : : utility : : sanitize_filename ( s ) ;
return s ;
} ;
CHECK ( sanitize_filename ( " abc/def " ) = = " abc/def " ) ;
CHECK ( sanitize_filename ( " abc/../def " ) = = " abc/_/def " ) ;
CHECK ( sanitize_filename ( " abc/.. \\ .. \\ ..//.../def " ) = = " abc/_ \\ _ \\ _//_./def " ) ;
CHECK ( sanitize_filename ( " abc/..../def " ) = = " abc/_../def " ) ;
CHECK ( sanitize_filename ( " abc/x../def " ) = = " abc/x../def " ) ;
CHECK ( sanitize_filename ( " ../etc/passwd " ) = = " _/etc/passwd " ) ;
CHECK ( sanitize_filename ( " abc/AUX " ) = = " abc/_ " ) ;
CHECK ( sanitize_filename ( " abc/AUX/foo " ) = = " abc/_/foo " ) ;
CHECK ( sanitize_filename ( " abc/AUX: " ) = = " abc/__ " ) ;
CHECK ( sanitize_filename ( " abc/AUXxy " ) = = " abc/AUXxy " ) ;
CHECK ( sanitize_filename ( " abc/AUX.xy " ) = = " abc/_.xy " ) ;
CHECK ( sanitize_filename ( " abc/NUL " ) = = " abc/_ " ) ;
CHECK ( sanitize_filename ( " abc/NU " ) = = " abc/NU " ) ;
CHECK ( sanitize_filename ( " abc/NuL " ) = = " abc/_ " ) ;
CHECK ( sanitize_filename ( " abc/LPT1 \\ " ) = = " abc/_ \\ " ) ;
CHECK ( sanitize_filename ( " abc/COM1 " ) = = " abc/_ " ) ;
CHECK ( sanitize_filename ( " ab?<>:*| \" cd " ) = = " ab_______cd " ) ;
CHECK ( sanitize_filename ( " abc/COM9 " ) = = " abc/_ " ) ;
CHECK ( sanitize_filename ( " abc/COM " ) = = " abc/COM " ) ;
CHECK ( sanitize_filename ( " abc/CON " ) = = " abc/_ " ) ;
2022-02-08 16:11:46 +00:00
CHECK ( sanitize_filename ( " /abc/ " ) = = " _abc/ " ) ;
2022-01-22 15:40:26 +00:00
}
2021-11-14 12:04:19 +00:00
TEST_CASE ( " get_port " )
{
SimpleApp app ;
const std : : uint16_t port = 12345 ;
2022-03-10 12:44:39 +00:00
auto _ = app . port ( port ) . run_async ( ) ;
2021-11-14 12:04:19 +00:00
app . wait_for_server_start ( ) ;
CHECK ( app . port ( ) = = port ) ;
app . stop ( ) ;
2021-11-25 11:45:38 +00:00
} // get_port
2021-11-17 11:14:33 +00:00
TEST_CASE ( " timeout " )
{
2021-11-27 12:28:50 +00:00
auto test_timeout = [ ] ( const std : : uint8_t timeout ) {
2021-11-25 11:45:38 +00:00
static char buf [ 2048 ] ;
2021-11-17 11:14:33 +00:00
2021-11-25 11:45:38 +00:00
SimpleApp app ;
2021-11-17 11:14:33 +00:00
2021-11-25 11:45:38 +00:00
CROW_ROUTE ( app , " / " )
2021-11-27 17:44:51 +00:00
( [ ] ( ) {
return " hello " ;
} ) ;
2021-11-17 11:14:33 +00:00
2022-03-10 12:44:39 +00:00
auto _ = app . bindaddr ( LOCALHOST_ADDRESS ) . timeout ( timeout ) . port ( 45451 ) . run_async ( ) ;
2021-11-25 11:45:38 +00:00
app . wait_for_server_start ( ) ;
asio : : io_service is ;
std : : string sendmsg = " GET / \r \n \r \n " ;
future_status status ;
2021-11-17 11:14:33 +00:00
2021-11-25 11:45:38 +00:00
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
2021-11-17 11:14:33 +00:00
2021-11-27 12:28:50 +00:00
auto receive_future = async ( launch : : async , [ & ] ( ) {
2021-11-27 17:44:51 +00:00
boost : : system : : error_code ec ;
c . receive ( asio : : buffer ( buf , 2048 ) , 0 , ec ) ;
return ec ;
} ) ;
2021-11-25 11:45:38 +00:00
status = receive_future . wait_for ( std : : chrono : : seconds ( timeout - 1 ) ) ;
CHECK ( status = = future_status : : timeout ) ;
2021-11-17 11:14:33 +00:00
2021-11-25 11:45:38 +00:00
status = receive_future . wait_for ( chrono : : seconds ( 3 ) ) ;
CHECK ( status = = future_status : : ready ) ;
CHECK ( receive_future . get ( ) = = asio : : error : : eof ) ;
2021-11-17 11:14:33 +00:00
2021-11-25 11:45:38 +00:00
c . close ( ) ;
}
{
asio : : ip : : tcp : : socket c ( is ) ;
c . connect ( asio : : ip : : tcp : : endpoint (
asio : : ip : : address : : from_string ( LOCALHOST_ADDRESS ) , 45451 ) ) ;
2021-11-17 11:14:33 +00:00
2021-11-25 11:45:38 +00:00
size_t received ;
2021-11-27 12:28:50 +00:00
auto receive_future = async ( launch : : async , [ & ] ( ) {
2021-11-27 17:44:51 +00:00
boost : : system : : error_code ec ;
received = c . receive ( asio : : buffer ( buf , 2048 ) , 0 , ec ) ;
return ec ;
} ) ;
2021-11-25 11:45:38 +00:00
status = receive_future . wait_for ( std : : chrono : : seconds ( timeout - 1 ) ) ;
CHECK ( status = = future_status : : timeout ) ;
2021-11-17 11:14:33 +00:00
2021-11-25 11:45:38 +00:00
c . send ( asio : : buffer ( sendmsg ) ) ;
2021-11-17 11:14:33 +00:00
2021-11-25 11:45:38 +00:00
status = receive_future . wait_for ( chrono : : seconds ( 3 ) ) ;
CHECK ( status = = future_status : : ready ) ;
CHECK ( ! receive_future . get ( ) ) ;
CHECK ( " hello " = = std : : string ( buf + received - 5 , buf + received ) ) ;
2021-11-17 11:14:33 +00:00
2021-11-25 11:45:38 +00:00
c . close ( ) ;
}
2021-11-17 11:14:33 +00:00
2021-11-25 11:45:38 +00:00
app . stop ( ) ;
} ;
2021-11-17 11:14:33 +00:00
2021-11-25 11:45:38 +00:00
test_timeout ( 3 ) ;
test_timeout ( 5 ) ;
} // timeout
2021-11-20 15:56:26 +00:00
TEST_CASE ( " task_timer " )
{
2021-11-25 11:45:38 +00:00
using work_guard_type = boost : : asio : : executor_work_guard < boost : : asio : : io_service : : executor_type > ;
boost : : asio : : io_service io_service ;
work_guard_type work_guard ( io_service . get_executor ( ) ) ;
2021-11-27 17:44:51 +00:00
thread io_thread ( [ & io_service ] ( ) {
io_service . run ( ) ;
} ) ;
2021-11-25 11:45:38 +00:00
bool a = false ;
bool b = false ;
crow : : detail : : task_timer timer ( io_service ) ;
CHECK ( timer . get_default_timeout ( ) = = 5 ) ;
timer . set_default_timeout ( 7 ) ;
CHECK ( timer . get_default_timeout ( ) = = 7 ) ;
2021-11-27 17:44:51 +00:00
timer . schedule ( [ & a ] ( ) {
a = true ;
} ,
2021-11-25 11:45:38 +00:00
5 ) ;
2021-11-27 17:44:51 +00:00
timer . schedule ( [ & b ] ( ) {
b = true ;
} ) ;
2021-11-25 11:45:38 +00:00
this_thread : : sleep_for ( chrono : : seconds ( 4 ) ) ;
CHECK ( a = = false ) ;
CHECK ( b = = false ) ;
this_thread : : sleep_for ( chrono : : seconds ( 2 ) ) ;
CHECK ( a = = true ) ;
CHECK ( b = = false ) ;
this_thread : : sleep_for ( chrono : : seconds ( 2 ) ) ;
CHECK ( a = = true ) ;
CHECK ( b = = true ) ;
io_service . stop ( ) ;
io_thread . join ( ) ;
} // task_timer