add unit-test

This commit is contained in:
ruanshudong 2021-08-23 15:40:10 +08:00
parent 5cc5cc4f3e
commit 743a64afbb
89 changed files with 13862 additions and 0 deletions

16
unit-test/CMakeLists.txt Executable file
View File

@ -0,0 +1,16 @@
project(unit-test)
include_directories(${CMAKE_SOURCE_DIR}/servant/protocol/framework)
include_directories(${CMAKE_SOURCE_DIR}/servant/protocol/servant)
include_directories(${CMAKE_BINARY_DIR}/src/gtest/include)
link_directories(${CMAKE_BINARY_DIR}/src/gtest/lib)
link_directories(${CMAKE_BINARY_DIR}/src/gtest/lib64)
include_directories(./)
build_tars_server("unit-test" "")
add_definitions(-DCMAKE_SOURCE_DIR="${PROJECT_SOURCE_DIR}")
target_link_libraries(unit-test ${LIB_GTEST})
add_dependencies(unit-test FRAMEWORK-PROTOCOL)

77
unit-test/certs.h Executable file
View File

@ -0,0 +1,77 @@
#ifndef PATH_HEAER
#define PATH_HEAER
#include "util/tc_config.h"
using namespace tars;
static const string CONFIGPATH(CMAKE_SOURCE_DIR);
inline TC_Config CONFIG()
{
string confFile = TC_Common::replace(TC_File::load2str(CONFIGPATH + "/server/hello.conf"), "PROJECT_PATH", CONFIGPATH);
TC_Config conf;
conf.parseString(confFile);
return conf;
}
inline TC_Config CLIENT_CONFIG()
{
string confFile = TC_Common::replace(TC_File::load2str(CONFIGPATH + "/server/client.conf"), "PROJECT_PATH", CONFIGPATH);
TC_Config conf;
conf.parseString(confFile);
return conf;
}
inline TC_Config FRAMEWORK_CONFIG()
{
TC_Config conf;
conf.parseFile(CONFIGPATH + "/server/framework.conf");
return conf;
}
inline TC_Config RPC1_CONFIG()
{
TC_Config conf;
conf.parseFile(CONFIGPATH + "/server/rpc1.conf");
return conf;
}
inline TC_Config RPC2_CONFIG()
{
TC_Config conf;
conf.parseFile(CONFIGPATH + "/server/rpc2.conf");
return conf;
}
inline TC_Config RPC3_CONFIG()
{
TC_Config conf;
conf.parseFile(CONFIGPATH + "/server/rpc3.conf");
return conf;
}
inline TC_Config WIN_CONFIG()
{
TC_Config conf;
conf.parseFile(CONFIGPATH + "/server/windows.conf");
return conf;
}
#define CA (CONFIGPATH + "/certs/ca.crt")
#define SERVER_CERT (CONFIGPATH + "/certs/server.crt")
#define CLIENT_CERT (CONFIGPATH + "/certs/client.crt")
#define SERVER_KEY (CONFIGPATH + "/certs/server.key")
#define CLIENT_KEY (CONFIGPATH + "/certs/client.key")
#endif

19
unit-test/certs/ca.crt Normal file
View File

@ -0,0 +1,19 @@
-----BEGIN CERTIFICATE-----
MIIDCzCCAfOgAwIBAgIUblg0MMUtu1YdIF1CmdlcKCXdg5gwDQYJKoZIhvcNAQEL
BQAwFTETMBEGA1UEAwwKKi5kZW1vLmNvbTAeFw0yMDAyMTQxMjQ5MDVaFw0zMzEw
MjMxMjQ5MDVaMBUxEzARBgNVBAMMCiouZGVtby5jb20wggEiMA0GCSqGSIb3DQEB
AQUAA4IBDwAwggEKAoIBAQCv8i3rLGi7j1E62fvpZ+9DI0kz6ASNOrmphzHS/E9p
X7EijiLpat+YARsYC42qA4+Cky1ItDTASUAkvVZNCj+6TNsFx1LSesgE28roOBOi
qXCtwBIQvAJBPRpgZtX5++BWyxexBsHszp8t1k7QKgVY3eXeGCQHOHZZltXNFGKP
2hruxct2VEcZWqWdYKE1hy0GSyxvejsT2GLv2OMlWwD/iE+UvTKU5+9CTq/vfx3j
vGUo410DniMz1OqqxAAamKhx4lzKvPfZeW/CQe929qwQONxGQENRXKiCiPkMTRIo
JCdXBDS6ztolq4URIB57yCq88qMO8ZY6URA6U97qyhlJAgMBAAGjUzBRMB0GA1Ud
DgQWBBSAwN6/0NtVoAWC7TB9PnYMzJhMJTAfBgNVHSMEGDAWgBSAwN6/0NtVoAWC
7TB9PnYMzJhMJTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBX
rGw19azPpFebPM5WHOUNBF5CesevnE4md0lE/9DcXl1wSLAwJC7bVijqt/gA4AgO
i+7AnVxlrrMZ4UBEgMu8cHyAGuaC/u+wSJ49TpciMk3/bKfN1gnQ1O/bzm8zpP/B
zQmffhiQcuM1wqStQeTnqD7bP4vAQKqLZGb0Hca2dPsRYIgW+z1dxLg6dxrFlkG8
dunwDDQXsnYf3PcB2fMQuK1lJltiiu7sVe+XeFeRTFSDGyxDs9q28SwRIHWlzIIC
j+57DkNAgBf9aYf7QM2dnmFNMHSs9fP8MZX7kltu5GadJKprDbjBtJd4IWSCMOv5
A/fdjurUkf3aCj1qGj+o
-----END CERTIFICATE-----

27
unit-test/certs/ca.key Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAr/It6yxou49ROtn76WfvQyNJM+gEjTq5qYcx0vxPaV+xIo4i
6WrfmAEbGAuNqgOPgpMtSLQ0wElAJL1WTQo/ukzbBcdS0nrIBNvK6DgToqlwrcAS
ELwCQT0aYGbV+fvgVssXsQbB7M6fLdZO0CoFWN3l3hgkBzh2WZbVzRRij9oa7sXL
dlRHGVqlnWChNYctBkssb3o7E9hi79jjJVsA/4hPlL0ylOfvQk6v738d47xlKONd
A54jM9TqqsQAGpioceJcyrz32XlvwkHvdvasEDjcRkBDUVyogoj5DE0SKCQnVwQ0
us7aJauFESAee8gqvPKjDvGWOlEQOlPe6soZSQIDAQABAoIBADujNRlPtjhM/dWa
6Z5V0m3JWhiz/kb4rtHdt2+ygiBPhTUXRJIl3aAiT9K4p84G4u/5fxHzsyWyLoHF
g6kdXjiBsIOm6lXZtE6hSYeo6k7qa/0Y64ask38VfQlMEh9n1sTUljU0+yqPZrkc
uR4qACH9JNtBB4VDCCqZy+J1lGr5jJjNB54Lv104bv0v5oF/CcT/D5r9fWbrFtKA
9RI4s0hc01ODlFOX8/N/Wemh/XMogi4Kt6n2Qkxdkt/eEheIs1oqbobO74rdXmOp
XhgLb/7QN9xqJVOsz7Bei4wevZYTj2IFAr5jpjoaItFP4aVw2QqiZwjdVPi8RhNg
TeaYxhkCgYEA4izPmmq7nWiisnkfTmWLp96OVcKDEP4RLdQcxC8sRgf8nj5SeVOj
pW2AXZ0sTDJQzjevox10keYDMeq0tgyBKAvmuHUMcHqUrNohvI6gbb40ldP40u1Q
Aqp1VCbHCaag/j5d30mVv6UTa47SB0V4e6a+xlfDvF6XuALO2Hp5qvMCgYEAxyW+
OZV63i8G3ZKUBm/CmUa0jqX+AVqGuH1ZEDJvHE/MGAmzcY99gAZSfRabHCBmP/8u
osYImu5ai+d8H/kV4MEYpuzHY445it0oUJPqYDjMlQja4ikRDrOE4evhs1rwXuV6
O65R9z2uGbMjBmUAe89J5n8e8MSLvslve60bwdMCgYEAr2Yg+ZecN85VniLgbGPD
kkO+DjPygNMHb4r3ZA1RQF4hQncCbqS2XCw3SGIDYHQExmfZBZ5qMFs4TxW9XxED
eJMCMjpTk0b81a+0Sg4xy+mdzjO825a+XdLjeoc4A/v9Di4/jlH6l8zk6pyvtIPj
k8EUYazeVs7kygcjci5I/JECgYB7h4HznjFU2L7deiqvw2tmQGGHipeAp3Khxb8V
OPOLEER9NKdGbcdfPoy0Yu1cCQzj7Zo0BbsYv3kTB0gLXSqg+6YbBQy5SGORK5Xy
RY5AmXrth0yetPKLt/dZXEPoSSSI+LdVhc/6GRyBfIjhUo12PyKMA5Zhqsk0UycA
BGUPWQKBgF745ohbFbAWgbbqRrFK6C8E3yAPfg5xOlve0p+yWbqe5Sv1NSQ+Zk3t
+7mBy6ygxNklq3oll8/9c7sYfnAZwdxGlqFj0Aj8CYOm81MfBfd6e1NYXgIaeh3z
MzeZRsobsroKUa2ULlyFmn2MX5HADo0YeTBYj6EZqT6VTAsKdPAN
-----END RSA PRIVATE KEY-----

1
unit-test/certs/ca.srl Normal file
View File

@ -0,0 +1 @@
5C1561567852EF51D268687494029145127A56C7

View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICsTCCAZkCFFwVYVZ4Uu9R0mhodJQCkUUSelbFMA0GCSqGSIb3DQEBCwUAMBUx
EzARBgNVBAMMCiouZGVtby5jb20wHhcNMjAwMjE0MTI0OTA2WhcNMzMxMDIzMTI0
OTA2WjAVMRMwEQYDVQQDDAoqLmRlbW8uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAzXLpEt1TWXzwWx6eQPGztqo7MSx8r3vxh5l5Wm45tRTNXot8
eh7QWvJChflUlnz9y0J7O2SxFnjdpHrp29AkLlt/aRjvRfLfgDcc7LqfUpWcc3qz
bkYPnktywXAuA1R3JnnsrDKFiwPY5Fc0bVuiZ0VZD9ufalvoc+kd3PjeQYvYkvUa
axZ0iaxKs5PaKwYIKW7RsWQa2bNkArH+slet50JDbDXuZXEnPghBLyjAhkhPmLQ8
jjrMX1t4fl0qQ21/q7TDf4FL+QNTcmEWQFEpz2H3qhM+J8UU2JdW36p+++Nj3CaF
lcWpCpxqJ8UGMqCfTM+KcPmBg/UQ/ByRb0wiqwIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQBMED94VcdZJwznIJ3FOyv+8D7P9PYS1KvIVclsC1G2Wzrhohx4sMcCE4QE
43TJDc0Vj/fQR+g3IyPL3TTWofLuif/Pp+7t2mieST7USrIWPJuUYYdkbch/WUEX
+p9vzdKJOnClCcdcMIptUJdHd7/X+qHPo0m4xg8qEfkW79IvcOQqAcl0Mx+Lxiny
Xps3VTe7j6IOdv4ZycD0OtYj3RSoQPfjWZ8yFV7riYjd0hj05sG/CNJ/9Nvy34tn
xRZnlWzMziOqYK+U/2BS1+j+LrfMJCgeShGdmBziqMde99Vovj2dv7sDvXqfZfCz
jLWfPO5ShCU72n7MoM/yqsTD8FmS
-----END CERTIFICATE-----

View File

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICWjCCAUICAQAwFTETMBEGA1UEAwwKKi5kZW1vLmNvbTCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAM1y6RLdU1l88FsenkDxs7aqOzEsfK978YeZeVpu
ObUUzV6LfHoe0FryQoX5VJZ8/ctCeztksRZ43aR66dvQJC5bf2kY70Xy34A3HOy6
n1KVnHN6s25GD55LcsFwLgNUdyZ57KwyhYsD2ORXNG1bomdFWQ/bn2pb6HPpHdz4
3kGL2JL1GmsWdImsSrOT2isGCClu0bFkGtmzZAKx/rJXredCQ2w17mVxJz4IQS8o
wIZIT5i0PI46zF9beH5dKkNtf6u0w3+BS/kDU3JhFkBRKc9h96oTPifFFNiXVt+q
fvvjY9wmhZXFqQqcaifFBjKgn0zPinD5gYP1EPwckW9MIqsCAwEAAaAAMA0GCSqG
SIb3DQEBCwUAA4IBAQCG6KZeU22DzRgfoljtuyPNuONyBPLsDbT2nhM8UFNS7Io9
hJYIn5FA57PC6vfJOPW4lvg5c73pjccJlLMYzPZ/TwvxUwcQzjeebZeRpPCB2fgQ
ihX/6pyN0s2Li2WK8dNq02y0bH+f+ItftCoFnrhJPfNxObaSpNQh7rIbkxujOprG
wqPmVFvEydzPwFwe6O42b2Ame+qdjva9QH4nbd8dG47kKCVhP8CMq8UbMvngVcbn
9A5dg4mS3OnTAdR21bNlZGQVHTiojKd3go7KrFwMlcRrCZ63+M510wIpUBxmFClA
icfaUazi62EikDnnFExu60xQ8MpWL9U57foKV8ci
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAzXLpEt1TWXzwWx6eQPGztqo7MSx8r3vxh5l5Wm45tRTNXot8
eh7QWvJChflUlnz9y0J7O2SxFnjdpHrp29AkLlt/aRjvRfLfgDcc7LqfUpWcc3qz
bkYPnktywXAuA1R3JnnsrDKFiwPY5Fc0bVuiZ0VZD9ufalvoc+kd3PjeQYvYkvUa
axZ0iaxKs5PaKwYIKW7RsWQa2bNkArH+slet50JDbDXuZXEnPghBLyjAhkhPmLQ8
jjrMX1t4fl0qQ21/q7TDf4FL+QNTcmEWQFEpz2H3qhM+J8UU2JdW36p+++Nj3CaF
lcWpCpxqJ8UGMqCfTM+KcPmBg/UQ/ByRb0wiqwIDAQABAoIBAQCTm5HVmeq+isNt
1CvDYWTLQrdQdzQGKLi5wgysajFP5ug+m10NqIHuNcyR0Tdy/86gcN11KL0K9j/Y
Yu8OnRbBr7901RNkYEEwL2i6tMKvZQqI9YlhGzkxc+e5D04f2lnY7RScC5hi7pqw
Q+9I+uNN60c324VHt0zlqoFoN+4HjJT786goeZVEBpUBVnJck31X7dtEpEDHFIaj
FMf7UPz+hA3vjB/tvK4gaBkCjPaNaYndTlclh8EHIPBFSoNX2EomIcluKclDgJfr
kVwGF/XAT0bHe9TABnp6/p08abYPKk6xUXZeBp7TjisRlslgcUbNAdeMQFThYwXH
0DXmiPSBAoGBAP48Qpxc33sYfMX5V0qZy5YLftgfhaV5ozPqBWGLQwSicx1pE/uQ
laYU4yBUVOsGOYwU72jU90DbCQvDb7F5I2gaznrUlb9cNIYn6pnSeHcUQP7+cFZS
ntp+uHDro0gRZcv+XMfOpHORErbzO/H9us8CmJhmCcDiY6ha789FC5iLAoGBAM7f
9q5P+DOpgydNCObCEujLv074I5Br/A/pjPzA/jHE8Hwflrwz4Suk1RcN1hQvaCOG
a8IIaKShYHG4UEy0yH/EPt/bK8tYzenVYOdoYIiVPTnrZYLkhKF9vLXEJWLzJOLd
TEKiwHMr2cKESLvfanSUU4/lYR2f7TWNGhyQqsJhAoGAMFviB8Aaul10DmxZUFVk
xku1ewKz9z/l7VAMafuFafJEl0mPhYCBFrBOa63e4T2z4JNy3qvzxCBl3hj0u/tg
4sKGmBKr0VSGoSYil9PTGkN+AYMAd0sL8F++UaxgyKqWhHED0PXbjigAOVCXDHbI
++twfzyZilkFv9ZcWz607/UCgYAdMgxdQ1ny6Ixi4oNMFb2XbxG7sldKjYLQOBS2
owH8wh9yVP7v5p5zi1qrWz+IL7yRrunMQ2WJPmEfC3UBrk3Rgj+hVgwTMaA1zPBV
GCzveahfYTI9S8TQCa+1M05XbZsaDUMy8EcaueiMhCDDqt8aPsigOS4AgU53zUcP
GveOYQKBgCokPs5b7Lbb8j1QjU7g8TJ4t9NhWfgMXYzet5djhbzpP/dSG9RaJn4Q
JOfUcMpQ3INkwq7t2T3PgZO3l8drBP52JscvzHYMgSdD0EbfIK5ekNMGE/G+0pD2
kALU50yc7f7FaP8142/sqlCg8cwMi6LQSN00hqw6yELQGKwjzRIs
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICsTCCAZkCFFwVYVZ4Uu9R0mhodJQCkUUSelbHMA0GCSqGSIb3DQEBCwUAMBUx
EzARBgNVBAMMCiouZGVtby5jb20wHhcNMjAwMjE0MTI0OTA2WhcNMzMxMDIzMTI0
OTA2WjAVMRMwEQYDVQQDDAoqLmRlbW8uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEA7Qw+OBtzkGG38r4IOBzgpJte5qHPCTBCeowt/6dmwY3W+1bU
cf5wdHBtSsuv3M5OpWKCG8gu3gpBZQvpz7MfN50ouuM0sDvKUxIUP2KX/nv7uiDg
R4iJy47M4XSH2qbRovKPZeRCeigkiU4gKMnJ0Vx82EgEdOLzBt1wLL8a0q1zVOwC
stII/0d4VhCoWgurddJa1gU7EwQ+ZRLwSbbvtgsEfVYCvwC/gb3fGrljJ2PpeY2/
UfxggnqGcG0IZoT4zi0uyRgK094nPVupS9JM5ig4I/FpP+KQ1LTlDh9LrwZrCQXj
/DFp0Wka5DWHTXWb7TwZShFo3r3emD3gGZi0owIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQB9+YqEgsabF3hh3OBFZmg0Je12mkFBsMCRPwMOXfEY8Mzt7xVHHx5iKsBa
u3XaLhVnOgu6VryGSIRmD7lGMctfIELysWu5xQtoY+m9xWZfDhY8G9sNhLSShJ/H
7UZ5/FUi+meohIM0SHEdzTyQtBSs+lfhgshsgtpZ4ysZDQTM/ukuOyBf1vXcs+Gx
pQa4hDQ+Tnev0h6z4PIDCeg88KohDgrzFMSFZ04bNUSLeIxjgo47hLxVNa/3xokh
yaTz4QZ3OcOjjfw//5lyfLDAZ7Rk1FBZ+NjdGRPjmTVIic2utT4QwS8aQyqDN/jA
gxo1xb+Tu5YxHXkMGa2hwV3VvhkF
-----END CERTIFICATE-----

View File

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICWjCCAUICAQAwFTETMBEGA1UEAwwKKi5kZW1vLmNvbTCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAO0MPjgbc5Bht/K+CDgc4KSbXuahzwkwQnqMLf+n
ZsGN1vtW1HH+cHRwbUrLr9zOTqVighvILt4KQWUL6c+zHzedKLrjNLA7ylMSFD9i
l/57+7og4EeIicuOzOF0h9qm0aLyj2XkQnooJIlOICjJydFcfNhIBHTi8wbdcCy/
GtKtc1TsArLSCP9HeFYQqFoLq3XSWtYFOxMEPmUS8Em277YLBH1WAr8Av4G93xq5
Yydj6XmNv1H8YIJ6hnBtCGaE+M4tLskYCtPeJz1bqUvSTOYoOCPxaT/ikNS05Q4f
S68GawkF4/wxadFpGuQ1h011m+08GUoRaN693pg94BmYtKMCAwEAAaAAMA0GCSqG
SIb3DQEBCwUAA4IBAQDrJMiKZIriezIo2PaJzm1Da4vcB41oiFVQGZuFRRN7Mt9t
tMDuZeVILSqkT1zHu0lamGuS/SKk1VSV0Or7S5Y2Bzm6MtsbVSpbMsRSj9HvXhZJ
lC6+YV1BfiZdSLdWPh/0vn6ku6/znKl8o68DvZyvSDoBahafbQluab/KGf85B0JP
vJ0AHAokfGMiragnKfJhPO18+IT5OClDDdjXbVs/PWx0SLt1EHjzqJOTNtvpDIw+
BZIiOcxhz7UjnGeyp5dvpnEbmhmk0WhZ0tsP2czOQwZIDesx2Nhbz/V45X1qDU3O
W0K9g37n7m1zsWHlA7LXwpSzG+wJTRWMOVGUxfyg
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA7Qw+OBtzkGG38r4IOBzgpJte5qHPCTBCeowt/6dmwY3W+1bU
cf5wdHBtSsuv3M5OpWKCG8gu3gpBZQvpz7MfN50ouuM0sDvKUxIUP2KX/nv7uiDg
R4iJy47M4XSH2qbRovKPZeRCeigkiU4gKMnJ0Vx82EgEdOLzBt1wLL8a0q1zVOwC
stII/0d4VhCoWgurddJa1gU7EwQ+ZRLwSbbvtgsEfVYCvwC/gb3fGrljJ2PpeY2/
UfxggnqGcG0IZoT4zi0uyRgK094nPVupS9JM5ig4I/FpP+KQ1LTlDh9LrwZrCQXj
/DFp0Wka5DWHTXWb7TwZShFo3r3emD3gGZi0owIDAQABAoIBAQCbBXWvJay20GEG
22XupFv46i7u7wTBgpEHKaNvXJ+jlsnwBsHaZsZOL7QZxQkWgskF+V0TJCAaT2Si
216l2QNiUGHxjmLHmeJf3yPkq+qwn45pE9T4kv9iYtnz20x5Hr1cLfq/bL5YuuXh
8Xiwk/5q72wp2Tco5b5/T9NrP/MfsNKpyGhFg3iuUfVWpbt9pHZQH+XRsv8N1j5J
vLpokbN4yu+vJAiFvbAFB3dUIgtsGO+z3yuYuaPnyAPpKJ2Ddj+yKhYZlLVitEgr
5SdiMY63fzg08LiJ4bdGNNBfa18rCTT2UiELDcs/g9+L/UQZLUgP43qYp3Gg9jwD
MqS36QgJAoGBAP6bxt31acB9/0iXGYYFNUzawTLJTmKY0lHtFL2ONshWyw/JTMDA
jwJYwtYP/Fonj6+021idhzy+2eneRvvk93ZD13kn9/LXHomjGNhvjY4C5RAy/eEv
eUxgLsEyMpBHREOdJaw+d0G70QDOpzp+iT1GbDI6xdxU1LqTmFzSpdwFAoGBAO5X
5aS4LS2xcGY3fuCbf8c1bATpl/pt5QmciUAfTdYcha09rm7oJULW1HujRUWNswdM
CRqBzGukQdzQ9VWcLRqCxjFenceCdS+W5W5f0ePTLV42LHbHyHcgDubwNHD3ZxOZ
fd5vxIAJOSK3U2Sey8Xy7gQTfnMoHUeiDRGI2FaHAoGBAPpspbFyzM00IH95fvU+
8inhj90v+xUnUtaZ5ah71I5AMAIa8I811nNsclax6neSKdWcgZIrfvTUkulgY1km
3+9G0wyrr0j/JV4jOTDIp+ZiGoNQZD20wA3LHLGRegJG1nHag09jMVFKNkwg9oKm
Kr5GIe1VuX75QTMyMM47sj8xAoGAbJVMwMNLidKZs2e6/Na62uWipYZKP8QLIVrY
SIc6bb4mxGsiadKHDzFSMlWKvIo2sq9YQmQ53hxCCTiFXJA/GCHV6y4A0aDEhH7J
XYR32cQemhoyHZcc4/CN+XYbXg/IPOyjpE/lBLOu/PrqGiAiE7d96gt7gzkWRck1
DPT8IkcCgYA519bOhJadqF7klt1VcJUm4bWDiZNy8SqnGwDUhV36TCvTILxxGIJj
GKsfDYwC/6icQa0U0pP58xgbB7ObHTfe2A2PtMN1Wx/Lu9Jnysn4pXbYOHADIKaF
Rtog1jYgGtIbaGhdZuPRURoJiPjm9N1ZNaZlAtQFsRWgk+sI7XLSvw==
-----END RSA PRIVATE KEY-----

47
unit-test/certs/create.sh Normal file
View File

@ -0,0 +1,47 @@
#create ca key
openssl genrsa -out ca.key 2048
#create ca crt
openssl req -x509 -new -nodes -key ca.key -subj "/CN=*.demo.com" -days 5000 -out ca.crt
#########################################################################################
#create server key
openssl genrsa -out server.key 2048
#create server csr
openssl req -new -key server.key -subj "/CN=*.demo.com" -out server.csr
#ca sign server, create server crt
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 5000
#########################################################################################
#create client key
openssl genrsa -out client.key 2048
#create clilent csr
openssl req -new -key client.key -subj "/CN=*.demo.com" -out client.csr
#ca sign client, create client crt
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 5000
#########################################################################################
#create server1 key
openssl genrsa -out server1.key 2048
#create server1 csr
openssl req -new -key server1.key -subj "/CN=*.demo.com" -out server1.csr
#ca sign server1, create server crt
openssl x509 -req -in server1.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server1.crt -days 5000
#########################################################################################
#create client1 key
openssl genrsa -out client1.key 2048
#create clilent1 csr
openssl req -new -key client1.key -subj "/CN=*.demo.com" -out client1.csr
#ca sign client1, create client1 crt
openssl x509 -req -in client1.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client1.crt -days 5000

View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICsTCCAZkCFFwVYVZ4Uu9R0mhodJQCkUUSelbEMA0GCSqGSIb3DQEBCwUAMBUx
EzARBgNVBAMMCiouZGVtby5jb20wHhcNMjAwMjE0MTI0OTA1WhcNMzMxMDIzMTI0
OTA1WjAVMRMwEQYDVQQDDAoqLmRlbW8uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEAwLHEXgjzTX6Z7MvPI1IAgwiEGuFyPl8b8o/tY9+2mvvs7EU4
oK3DDRFoGwkTGfuLwstuhKllE2QyIr5QN6FmfWWiitjOovlEVRTJ5a274YXes9Kz
uFlw6RT9WDj2iEkgdB7KWfQjaoCWrjhNt1rzh/jRpcmHsLmpOiQYBPeIpqVTnK1o
risQ6352qnmperB8lcj731rKebDwZIo9y5nL/qDzwH3dBJQeFqvNuPcSd76lrpy+
9GTA3lFgQQJyUiSwzBD005LKKW4fEcdllPa+/jLAuKO/atm+6dv186w7ojIMceir
549jn9UUyvWXfSfXl+68Aku1FTFFhRdS6OMsWQIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCLCr8rsrgZskc3Ou7dZ5Br8xA2m7lrLSkFQIsDRosfBPerhGr83mgeyp2+
DNbPy0+IzgBUyN8N/P3QlZbQFq/3u9bjih3QukJuJe6KfYI0/iQu5jHxFv7VgbE+
a8yqUsrirWsmpltOMobv19jtWm/v1kofvCIUSBCJXkVi2L75164MhkKTGbSV1dl/
Ujg+X9yss5ZcDR+MqzuHZOO9580Ky0p+9m+STpZFG7QvC9QQtbvUBogAWECg+sSB
RQ7Maq337ERpJg5EGOG2R+sa8rssMGFMRJ9OfenS+KaRF/oNKKL12pG7Y+oYpfEj
WfSt4Lv16RWdV2vkmrorTovSuTIa
-----END CERTIFICATE-----

View File

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICWjCCAUICAQAwFTETMBEGA1UEAwwKKi5kZW1vLmNvbTCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAMCxxF4I801+mezLzyNSAIMIhBrhcj5fG/KP7WPf
tpr77OxFOKCtww0RaBsJExn7i8LLboSpZRNkMiK+UDehZn1loorYzqL5RFUUyeWt
u+GF3rPSs7hZcOkU/Vg49ohJIHQeyln0I2qAlq44Tbda84f40aXJh7C5qTokGAT3
iKalU5ytaK4rEOt+dqp5qXqwfJXI+99aynmw8GSKPcuZy/6g88B93QSUHharzbj3
Ene+pa6cvvRkwN5RYEECclIksMwQ9NOSyiluHxHHZZT2vv4ywLijv2rZvunb9fOs
O6IyDHHoq+ePY5/VFMr1l30n15fuvAJLtRUxRYUXUujjLFkCAwEAAaAAMA0GCSqG
SIb3DQEBCwUAA4IBAQBLD12Bwb5YZE0PSLMm37/KMoN1nl1bug002HXGjtK48I+J
8pyd4BX5yW69gIP/CeHouDqJ/vhTdJmm/mLsexcby21RW55XYouCGLT/Cmh5qj+K
HmcMR6lo38Q324cjNaMiqX8yAthbfWIC2Wupzb69SUiaXqXZ7F5dC+tB8DSVEvIY
LBwxcXQBHC4C4k5aCIaPTlA20wdT0CKmD914Jby+iP5HP64nvc5yxacjKO+uOwNB
AZe/uLWeCJs6v372oiFaiN+m8EQhmcD/2i8qSiFCcC3V3MRAZitoJseaYnRR9Aev
wYCI6lpn2nCdM/L0+uOxZ2sA3hkb2muoUSPaRLq/
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAwLHEXgjzTX6Z7MvPI1IAgwiEGuFyPl8b8o/tY9+2mvvs7EU4
oK3DDRFoGwkTGfuLwstuhKllE2QyIr5QN6FmfWWiitjOovlEVRTJ5a274YXes9Kz
uFlw6RT9WDj2iEkgdB7KWfQjaoCWrjhNt1rzh/jRpcmHsLmpOiQYBPeIpqVTnK1o
risQ6352qnmperB8lcj731rKebDwZIo9y5nL/qDzwH3dBJQeFqvNuPcSd76lrpy+
9GTA3lFgQQJyUiSwzBD005LKKW4fEcdllPa+/jLAuKO/atm+6dv186w7ojIMceir
549jn9UUyvWXfSfXl+68Aku1FTFFhRdS6OMsWQIDAQABAoIBAQCQot5qVv2JJYYU
H8cTE/IeaL4AD0jZWDp6D154oOtH2eE0V6Dxunu1y2MBKAaWciGtzVTfbubXb1XS
jldX6mYrqaYf4iz4V3HbCwegxo9H8FwBTh5oOXpu+bpQBjHGil05zALHEmGjB3IS
w2BSSIqTfUif0G1xUWqcoYsF72c67X0O2lFhhJdG+pP9jje1xliPVzRX4YHfNOj0
erxfaZlljYNSN9c4l/GwCMsoXyYSsrCqp8LfM8TLO99MiZNpzP4uwTJcqV+bxOkA
t6/L78Y/YwYps5bWbhkVBU8osPqX9CsjCvuG3b8aElBHDjclWZqp5E8/N32+Zcxz
w5z+wcgBAoGBAP6xCRLP+LvFzMBkO5jgsIfXrv5EhTtzhslk9ZVHNvoI9BHgp/6s
XzZOn5lgS+7RB4E6V3UPOPNq11lEPVLrW6OIraUhQsbyUa8TS2DITtEm4HmV3QZ9
4yoDPDxUWy5KT8DnKuHfL55u7KC38DtmsHzgHFQ0aUuvHL5zBokCAY/5AoGBAMGv
McLCZX7C7nr9FQd2lJf/LL9zq0Aq+XDuU1T9lvCwZ28tbCfIU/5DZIha8kGTWiis
Q7gvk3KHv5UenOfYhiXj7VwdP2ulKibGPCbAwFCD4fciecg8ah17WDhHmHoVUdAw
KIBf69VjHBuDpT0tfDmvYDNpblr2kbPb+/fkzldhAoGBAKZWlSh2L2rjSlA0pj+4
L1Lo6F8j/SfQ0azihQnTkvJFurGaWd2YUi6ztsSDAdSdLBuYMNpA8N75Xl/sk2h+
UkFB2LbKPESWqgZ/wXEaIW+zxlNiLxI4UY50wnhcV5ip6+B+maEfFIiSxXRJ7Vm+
PXGxJI9SE5rcaRdxJEmCx+ZxAoGAKtl6lc7yK2gu4JDLLTqDx1jR6o1JjsmzI9Pm
JcBwu1EboRIYgnikdHUucahFPlK+OI9b8Ay+fzEfJnt+VSCnFQzm/2ENHeCNgcSL
nDs6kNWMkWNUNAOBqoIWU2Uri57Z2cg9vaD7CNuDZWbrkKxWdmChVN53ZrJ0K6l4
hjBdoiECgYA2jgAPqVMY+12vipImOAZ9+/Ly8aVgFqZFN4DJOk8HjvMlBOEfq/cJ
cOPMgS2yZ8Rtqg/u7YxFBSVuLwqH/u+q/Ld1rymALM8Ilja0A7FPUUTnuq6iYFD9
n/1eQW6jCQQY+ALo2MIZ4co0MviK8lj4kC8occqojllFQPU88xt32w==
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICsTCCAZkCFFwVYVZ4Uu9R0mhodJQCkUUSelbGMA0GCSqGSIb3DQEBCwUAMBUx
EzARBgNVBAMMCiouZGVtby5jb20wHhcNMjAwMjE0MTI0OTA2WhcNMzMxMDIzMTI0
OTA2WjAVMRMwEQYDVQQDDAoqLmRlbW8uY29tMIIBIjANBgkqhkiG9w0BAQEFAAOC
AQ8AMIIBCgKCAQEA3o5I31gvK3AiF0sFAtHSt1diLMZEG1JtkeaKm9lIQgzqdG8+
f2nZPVAvU66M3B6uiYMU/QQVh3KAXF5bMyKhJtLGNYHqj6VoJatvWVdb1iasQW9M
8eGl2exxDMTPHWJ44vOYLcXJ6M3WRcfIXHC9K3rIjz2bWjDqHU8Y0fecCSJX8ctR
gxgNBwM41P45dExbxQp5RGye7TOfXnf0yQJReFx2JDzzYqQ61VoqlkTw2RkuSr0Q
ydr8S7CuReWF0xbKzMGf1L+SzmyGB2SAc9jkJ7T3Y4B36iy3y8hvMBTbCmke4ZpO
FDrTw95wfC611nTXNKjUOlulKxSf+cfhACPFWwIDAQABMA0GCSqGSIb3DQEBCwUA
A4IBAQCpQEXaFJiXSLeL9HKnvIexlxWfjTvikMoNR0t3UMxShazKE5gkQSw3WtCo
E+LmmDvt0bqn54fk77oWxwZTx/qe8vJwpo0/gl/tNnGnzdzIAXk10G1W7kWkU2eG
gpvYcQXKpW0QORHRzEXMbGIzdqjZOaFZYA+VtbtFB0cSLx8eNtd/bKxtwZyl66es
uhPF40TnH6ccyq0Z2WuQylG4aSZ7qQcxCJUKj/Ych1+wr45ncgTZIsKXPBd0k7Kx
xYvEuW8WGSjpJD8qPXt8hEwWpOfwLsmpnF1kMyaONLSHcqhfNU0bPTolLUSDJxkY
0JVVfeStdEsrmos1SrpEjD+wGlng
-----END CERTIFICATE-----

View File

@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICWjCCAUICAQAwFTETMBEGA1UEAwwKKi5kZW1vLmNvbTCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAN6OSN9YLytwIhdLBQLR0rdXYizGRBtSbZHmipvZ
SEIM6nRvPn9p2T1QL1OujNweromDFP0EFYdygFxeWzMioSbSxjWB6o+laCWrb1lX
W9YmrEFvTPHhpdnscQzEzx1ieOLzmC3FyejN1kXHyFxwvSt6yI89m1ow6h1PGNH3
nAkiV/HLUYMYDQcDONT+OXRMW8UKeURsnu0zn1539MkCUXhcdiQ882KkOtVaKpZE
8NkZLkq9EMna/EuwrkXlhdMWyszBn9S/ks5shgdkgHPY5Ce092OAd+ost8vIbzAU
2wppHuGaThQ608PecHwutdZ01zSo1DpbpSsUn/nH4QAjxVsCAwEAAaAAMA0GCSqG
SIb3DQEBCwUAA4IBAQBUY5PIac76NGf+rHFG0xAXrZDuttwJOUjywz0La//+iPPK
RFm+x+LK5tLc6Iunfo3Po7BedISIQ1+QxA8l2x6SmEczrJxGolwgjkj4iozhL5m+
UKbsKF6V+3ZF7wHcbVZ9dCQsr6dO39Qg4x07U0DUDll4L3bk7cMyZBX2WAq3Tp6u
jBJI96A8VcnVs0lTghQNfJlGBv6OFPXJPHpgJucZ/e4Kpbr/bMxVF/bRRoEaNz1G
1JbieeB4Ohv0P3SzYTj4zgOYV1NTizg1a7SeODFJ3uDtGm2oN3TAzE6yg3ngzxvk
u+F5d+KbhSewBe/AuAWIK1Jn1Ez3NGMoR5zMbKCg
-----END CERTIFICATE REQUEST-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA3o5I31gvK3AiF0sFAtHSt1diLMZEG1JtkeaKm9lIQgzqdG8+
f2nZPVAvU66M3B6uiYMU/QQVh3KAXF5bMyKhJtLGNYHqj6VoJatvWVdb1iasQW9M
8eGl2exxDMTPHWJ44vOYLcXJ6M3WRcfIXHC9K3rIjz2bWjDqHU8Y0fecCSJX8ctR
gxgNBwM41P45dExbxQp5RGye7TOfXnf0yQJReFx2JDzzYqQ61VoqlkTw2RkuSr0Q
ydr8S7CuReWF0xbKzMGf1L+SzmyGB2SAc9jkJ7T3Y4B36iy3y8hvMBTbCmke4ZpO
FDrTw95wfC611nTXNKjUOlulKxSf+cfhACPFWwIDAQABAoIBADGK4QP/AHkd/CjN
RW9MQCkaJbur4ytl3QhWltJ8uw4hC+whe3snl/mDKRXqzGaP2fC4omp0h0pgndxy
EMFAWzlmQENXCV0yyA1irWXpAYOZlkz2tt09iwsJDF14TlbPPfPfoCfIWNsfPyzH
fX2+hw3vxkfEwhmAvA0MN40+HpkVhsg2nEMGnFYmViFtVW5smZ/xt9kBenzdhC3X
OUmRZy5/MlFfTCPpf0NBG2rDMqwDUqdghRVza84cnC+iOoV7fb2YFjjhRUhYPbvs
EM4S0nSZ6QoR8k82UItJmjV2LaEQ3R0GNDaTyOMB1+hvR0Jarfp6DAjnw8euRQlL
wSEIV7kCgYEA9Xk8/Aoj4B1yoGXVOCwKrdO4IaLjS9N8ZN1WVEYAh1yDTy+FvJXk
qCoiiHgot18Hgz6vwrUp5YYQJ5VaSJyvU+N0cX5G2Qec4KIJnftzPcIagxCx+Kvv
APp2UGSGX40CEcJP29L0O02TQNcHESu5SJAG11n+w+L1CH+uLMFbdVUCgYEA6Bl1
meV8tLdnAMaOU5oG9vu0J9Gp1Ncj/KkvZkZ9v8rppmkmXkcl9ZaXsaHCE1etEwnj
/Xxe8dw9C1gdbKF/AmCKIGfaO+7T5CSORLdULlRmgK1ejhphce7ruNxcOY9K1O/s
tB1NsbLxRj3MCIS51Or/Zss0Pt9CRT1WUrhcT+8CgYEAyh1mGjwbJ+f3Ppw6QEL7
E/8USBW/QurCLKaV81OkEdAZifSeEBX3LINs5aLSG5HSNL1DqHTUJ1kIKh9uNAVW
0yKf+Oa5XO9IuyiP9JVaYMpWW/4+G3stkkenbTAn97q5rneom14JnF6WVTf3aKrw
pw93oo9GFnHjwXinp9AZBvUCgYEAylRfY3BdvQBgh5mPuyt7xNT5YPjyLvv5gClQ
i70JpCdUdeAWNXuaiLPlu1EC6W+2DfHCUViZQAg5IumGhQtnt//Giade5H43Mxv2
9cpHVTf4P1ZjJkezCOo5jWZz8y2KE4Sv+PfOogkXMZ9vfUGO6iCN0uNzwRdJIyjs
VqImvvsCgYAeimY5ZUIKKXPSjEI/k0mEAcYrIY4JVRn1ZN6AZju0L50k0QM+VZFp
FKhfm79TGCsoWgufa4Dhe5H4gMx1UtkYVpvPnkvlcPYCsLSiSXYZO7A6fOgrPdny
15IUMoM/8DfYtEiFa3sQRd/yhhDMHk4RFtE380BpUlds17PWS7zRjQ==
-----END RSA PRIVATE KEY-----

1010
unit-test/hello_test.cpp Executable file

File diff suppressed because it is too large Load Diff

368
unit-test/hello_test.h Executable file
View File

@ -0,0 +1,368 @@
#include "server/HelloServer.h"
#include "server/Hello.h"
#include "gtest/gtest.h"
#include "certs.h"
#include <mutex>
#include <iostream>
using namespace tars;
using namespace Test;
class PushCallBack : public ServantProxyCallback
{
public:
int onDispatch(ReqMessagePtr msg)
{
if(msg->request.sFuncName == "printResult")
{
string sRet;
sRet.assign(&(msg->response->sBuffer[0]), msg->response->sBuffer.size());
_onprintresult = true;
// printResult(msg->request.iRequestId, sRet);
return 0;
}
else if(msg->response->iRequestId == 0)
{
string sRet;
sRet.assign(&(msg->response->sBuffer[0]), msg->response->sBuffer.size());
++_onpushinfo;
// printPushInfo(sRet);
return 0;
}
else
{
LOG_CONSOLE_DEBUG << "no match func!" <<endl;
}
return -3;
}
void onConnect(const TC_Endpoint &ep)
{
_onconnect = true;
// LOG_CONSOLE_DEBUG << "onConnect:" << ep.toString() << ", " << _onconnect << ", " << this << endl;
}
void onClose()
{
_onclose = true;
// LOG_CONSOLE_DEBUG << "onClose:" << _onclose << endl;
}
bool _onclose = false;
bool _onconnect = false;
bool _onprintresult = false;
int _onpushinfo = 0;
};
typedef tars::TC_AutoPtr<PushCallBack> PushCallBackPtr;
struct ClientHelloCallback : public HelloPrxCallback
{
ClientHelloCallback(int64_t t, int i, int c, const string &buff, std::atomic<int> &count) : start(t), cur(i), count(c), buffer(buff), callback_count(count)
{
}
ClientHelloCallback(HelloPrx prx, std::atomic<int> &count) : _prx(prx), callback_count(count)
{
}
//回调函数
virtual void callback_testTrans(int ret, const string &r);
//回调函数
virtual void callback_testHello(int ret, const string &r);
virtual void callback_testSyncTrans(tars::Int32 ret, const std::string& r);
virtual void callback_testHello_exception(tars::Int32 ret)
{
LOG_CONSOLE_DEBUG << "callback exception:" << ret << endl;
exit(-1);
}
virtual void callback_testTrans_exception(tars::Int32 ret)
{
LOG_CONSOLE_DEBUG << "callback exception:" << ret << endl;
exit(-1);
}
virtual void callback_testSyncTrans_exception(tars::Int32 ret)
{
LOG_CONSOLE_DEBUG << "callback exception:" << ret << endl;
exit(-1);
}
virtual void callback_testTimeout(int ret)
{
callback = true;
}
virtual void callback_testTimeout_exception(tars::Int32 ret)
{
callback_exception = true;
}
HelloPrx _prx;
bool callback = false;
bool callback_exception = false;
int64_t start;
int cur;
int count;
string buffer;
std::atomic<int> &callback_count;
};
struct HelloHttpCallback : public HttpCallback
{
HelloHttpCallback(int64_t t, int i, int c, const string &buff, std::atomic<int> &count) : start(t), cur(i), count(c),_buff(buff), callback_count(count)
{
}
virtual int onHttpResponse(const shared_ptr<TC_HttpResponse> &rsp)
{
[&]()
{
ASSERT_TRUE(rsp->getContent() == _buff);
}();
callback_count++;
if(cur == count-1)
{
int64_t cost = TC_Common::now2us() - start;
LOG_CONSOLE_DEBUG << "count:" << count << ", " << cost << " us, avg:" << 1.*cost/count << "us" << endl;
}
return 0;
}
virtual int onHttpResponseException(int expCode)
{
LOG_CONSOLE_DEBUG << "onHttpResponseException expCode:" << expCode << endl;
return 0;
}
int64_t start;
int cur;
int count;
string _buff;
std::atomic<int> &callback_count;
};
class CustomCallBack : public ServantProxyCallback
{
public:
CustomCallBack(std::atomic<int> &count) : callback_count(count) {}
virtual int onDispatch(ReqMessagePtr msg)
{
if(msg->response->iRet != tars::TARSSERVERSUCCESS)
{
cout << "ret error:" << msg->response->iRet << endl;
}
else
{
// cout << "succ:" << string(msg->response->sBuffer.data(), msg->response->sBuffer.size()) << endl;
}
++callback_count;
return msg->response->iRet;
}
virtual void onClose()
{
}
std::atomic<int> &callback_count;
};
typedef tars::TC_AutoPtr<CustomCallBack> CustomCallBackPtr;
class HelloTest : public testing::Test
{
public:
//添加日志
static void SetUpTestCase()
{
}
static void TearDownTestCase()
{
}
virtual void SetUp()
{
_buffer.assign(100, 'a');
_conf = CONFIG();
}
virtual void TearDown()
{
LOG_CONSOLE_DEBUG << "fd count:" << getFdCounts() << endl;
}
template<typename T>
void startServer(T &server, TC_Config conf, TC_EpollServer::SERVER_OPEN_COROUTINE openCoroutine = TC_EpollServer::NET_THREAD_MERGE_HANDLES_THREAD)
{
// TC_Config conf;
// conf.parseFile(config);
conf.set("/tars/application/server<opencoroutine>", TC_Common::tostr(openCoroutine));
ASSERT_TRUE(conf.get("/tars/application/server<opencoroutine>") == TC_Common::tostr(openCoroutine));
// ASSERT_TRUE(ServerConfig::OpenCoroutine == openCoroutine);
server.main(conf.tostr());
server.start();
server.waitForReady();
}
void startServer(HelloServer &server, TC_EpollServer::SERVER_OPEN_COROUTINE openCoroutine);
template<typename T>
void stopServer(T &server)
{
server.terminate();
server.getThreadControl().join();
}
TC_Endpoint getEndpoint(const string &adapter);
string getObj(TC_Config &conf, const string &adapter)
{
return conf.get("/tars/application/server/" + adapter + "<servant>") + "@" + conf.get("/tars/application/server/" + adapter + "<endpoint>");
}
TC_Endpoint getEndpoint(TC_Config &conf, const string &adapter)
{
return TC_Endpoint(conf.get("/tars/application/server/" + adapter + "<endpoint>"));
}
TC_Endpoint getLocalEndpoint(const TC_Config &conf)
{
return TC_Endpoint(conf.get("/tars/application/server<local>"));
}
template<typename T>
T getObj(Communicator *comm, const string &adapter)
{
comm->setProperty("sendqueuelimit", "1000000");
// comm->setProperty("asyncqueuecap", "1000000");
string obj = getObj(_conf, adapter);
T prx = comm->stringToProxy<T>(obj);
prx->tars_timeout(60000);
prx->tars_async_timeout(60000);
return prx;
}
int getFdCounts()
{
//linux下才生效, 其他平台都是返回的0
vector<string> fds;
TC_File::listDirectory("/proc/" + TC_Common::tostr(getpid()) + "/fd", fds, false);
return fds.size();
}
int getSocketFd(int iSocketType = SOCK_DGRAM, int iDomain = AF_INET)
{
TC_Socket s1;
s1.createSocket(iSocketType, AF_INET);
s1.setOwner(false);
return s1.getfd();
}
void waitForFinish(atomic<int> &callback_count, int count);
void wait(int millseconds);
void syncCustom(Communicator *comm, const string &adapter = "CustomAdapter");
void asyncCustom(Communicator *comm, const string &adapter = "CustomAdapter");
void testPush(Communicator *comm, const string &adapter = "PushAdapter");
void testReconnect(Communicator *comm, const string &adapter = "PushAdapter");
void checkWup();
void checkSyncHttp(Communicator *comm, const string &adapter = "HttpAdapter", bool close = false);
void checkASyncHttp(Communicator *comm, const string &adapter = "HelloAdapter", bool close = false);
void checkSync(Communicator *comm, const string &adapter = "HelloAdapter");
void checkSyncOnce(HelloPrx prx);
void checkASyncOnce(HelloPrx prx);//Communicator *comm, const string &adapter = "HelloAdapter");
void checkASync(Communicator *comm, const string &adapter = "HelloAdapter");
void checkTransSyncASync(Communicator *comm);
void checkTransASyncASync(Communicator *comm);
void checkTransSyncSync(Communicator *comm);
void checkTransASyncSync(Communicator *comm);
void checkWupTransSync(Communicator *comm);
void checkSyncTimeout(Communicator *comm);
void checkASyncTimeout(Communicator *comm);
void checkStat(Communicator *comm, int reportCount);
void rpcFromRegistry(Communicator *comm);
void forEach(function<void()> func);
void forEach(function<void(Communicator *comm)> func);
void transGlobalCommunicator(function<void(Communicator *)> func, Communicator *comm);
void transServerCommunicator(function<void(Communicator *)> func);
void transAllocCommunicator(function<void(Communicator *)> func);
void transComplexCommunicator(function<void(Communicator *)> func, Communicator *comm);
void funcInCoroutine(function<void()> func, bool setSched = true);
void forEachInCoroutine(function<void(Communicator *comm)> func);
void transInCoroutineGlobalCommunicator(function<void(Communicator *)> func, Communicator *comm);
void transInCoroutineServerCommunicator(function<void(Communicator *)> func);
void transInCoroutineAllocCommunicator(function<void(Communicator *)> func);
void transInCoroutineComplexCommunicator(function<void(Communicator *)> func, Communicator *comm);
shared_ptr<Communicator> getCommunicator();
protected:
int _count = 1000;
// int _count = 10;
string _buffer;
TC_Config _conf;
};

19
unit-test/main.cpp Normal file
View File

@ -0,0 +1,19 @@
#include <cassert>
#include <iostream>
#include <vector>
#include "util/tc_common.h"
#include "util/tc_logger.h"
#include "gtest/gtest.h"
using namespace std;
using namespace tars;
int main(int argc, char** argv)
{
#if TARGET_PLATFORM_LINUX || TARGET_PLATFORM_IOS
tars::TC_Common::ignorePipe();
#endif
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

97
unit-test/rpc/test_admin.cpp Executable file
View File

@ -0,0 +1,97 @@
/**
* Tencent is pleased to support the open source community by making Tars available.
*
* Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
#include "hello_test.h"
#include "../server/WinServer.h"
#include "servant/AdminF.h"
#include "server/FrameworkServer.h"
#include "server/framework/DbHandle.h"
TEST_F(HelloTest, testAdmin)
{
FrameworkServer fs;
startServer(fs, FRAMEWORK_CONFIG());
CDbHandle::cleanEndPoint();
CDbHandle::addActiveEndPoint("TestApp.FrameworkServer.ConfigObj", 11003, 1);
WinServer ws;
startServer(ws, WIN_CONFIG());
// auto c = getCommunicator();
CommunicatorPtr c = ws.getCommunicator();
string adminObj = "AdminObj@" + getLocalEndpoint(WIN_CONFIG()).toString();
AdminFPrx adminFPrx = c->stringToProxy<AdminFPrx>(adminObj);
string loadconfig = adminFPrx->notify("tars.loadconfig test.conf");
EXPECT_TRUE(loadconfig.find("[succ] get remote config:") != string::npos);
loadconfig = adminFPrx->notify("tars.loadconfig no-test.conf");
EXPECT_TRUE(loadconfig.find("[fail] get remote config ") != string::npos);
string setloglevel = adminFPrx->notify("tars.setloglevel DEBUG");
EXPECT_TRUE(setloglevel.find("set log level [DEBUG] ok") != string::npos);
string viewstatus = adminFPrx->notify("tars.viewstatus");
EXPECT_TRUE(viewstatus.find("notify prefix object num:1") != string::npos);
string viewversion = adminFPrx->notify("tars.viewversion");
EXPECT_TRUE(viewversion.find("$") != string::npos);
string connection = adminFPrx->notify("tars.connection");
EXPECT_TRUE(connection.find("[adater:AdminAdapter] [connections:1]") != string::npos);
ServerConfig::ConfigFile = CONFIGPATH + "/server/windows.conf";
string loadproperty = adminFPrx->notify("tars.loadproperty");
EXPECT_TRUE(loadproperty.find("loaded config items:") != string::npos);
string help = adminFPrx->notify("tars.help");
EXPECT_TRUE(help.find("tars.closecore") != string::npos);
string closecout = adminFPrx->notify("tars.closecout NO");
string enabledaylog = adminFPrx->notify("tars.enabledaylog local|daylog|true");
EXPECT_TRUE(enabledaylog.find("set local daylog true ok") != string::npos);
enabledaylog = adminFPrx->notify("tars.enabledaylog remote|false");
EXPECT_TRUE(enabledaylog.find("set remote false ok") != string::npos);
string reloadlocator = adminFPrx->notify("tars.reloadlocator reload");
EXPECT_TRUE(reloadlocator.find("[notify prefix object num:1]") != string::npos);
// string closecore = adminFPrx->notify("tars.closecore no");
// EXPECT_TRUE(closecore.find("after set cur:18446744073709551615;max: 18446744073709551615") != string::npos);
// closecore = adminFPrx->notify("tars.closecore yes");
// EXPECT_TRUE(closecore.find("after set cur:0;max: 18446744073709551615") != string::npos);
string errorcmd = adminFPrx->notify("tars.errorcmd");
EXPECT_STREQ(errorcmd.c_str(), "");
string normalcmd = adminFPrx->notify("AdminCmdNormalTest returnMark");
EXPECT_STREQ(normalcmd.c_str(), "[notify servant object num:1]\n[1]:returnMark AdminCmdNormalTest success!\n");
string normaldeletecmd = adminFPrx->notify("DeletePrefixCmd");
EXPECT_STREQ(normaldeletecmd.c_str(), "[notify servant object num:1]\n[1]:Delete success!\n");
stopServer(ws);
stopServer(fs);
}

134
unit-test/rpc/test_async_rpc.cpp Executable file
View File

@ -0,0 +1,134 @@
#include "hello_test.h"
TEST_F(HelloTest, rpcASyncGlobalCommunicator)
{
shared_ptr<Communicator> c = getCommunicator();
transGlobalCommunicator([&](Communicator *comm){
checkASync(comm);
}, c.get());
}
TEST_F(HelloTest, rpcASyncGlobalCommunicatorInCoroutine)
{
shared_ptr<Communicator> c = getCommunicator();
transInCoroutineGlobalCommunicator([&](Communicator *comm){
checkASync(comm);
}, c.get());
}
TEST_F(HelloTest, rpcASyncServerCommunicator)
{
transServerCommunicator([&](Communicator *comm){
checkASync(comm);
});
}
TEST_F(HelloTest, rpcASyncServerCommunicatorInCoroutine)
{
transInCoroutineServerCommunicator([&](Communicator *comm){
checkASync(comm);
});
}
TEST_F(HelloTest, rpcASyncAllocCommunicator)
{
transAllocCommunicator([&](Communicator *comm){
checkASync(comm);
});
}
TEST_F(HelloTest, rpcASyncAllocCommunicatorInCoroutine)
{
transInCoroutineAllocCommunicator([&](Communicator *comm){
checkASync(comm);
});
}
TEST_F(HelloTest, rpcASyncComplexCommunicator)
{
shared_ptr<Communicator> c = getCommunicator();
transComplexCommunicator([&](Communicator *comm){
checkASync(comm);
}, c.get());
transComplexCommunicator([&](Communicator *comm){
checkASync(comm);
}, c.get());
transComplexCommunicator([&](Communicator *comm){
checkASync(comm);
}, c.get());
transComplexCommunicator([&](Communicator *comm){
checkASync(comm);
}, c.get());
}
TEST_F(HelloTest, rpcASyncComplexCommunicatorInCoroutine)
{
shared_ptr<Communicator> c = getCommunicator();
transInCoroutineComplexCommunicator([&](Communicator *comm)
{
checkASync(comm);
},
c.get());
transInCoroutineComplexCommunicator([&](Communicator *comm){
checkASync(comm);
}, c.get());
transInCoroutineComplexCommunicator([&](Communicator *comm){
checkASync(comm);
}, c.get());
transInCoroutineComplexCommunicator([&](Communicator *comm){
checkASync(comm);
}, c.get());
}
TEST_F(HelloTest, rpcASyncThreadFinish)
{
shared_ptr<Communicator> c = getCommunicator();
HelloServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) 0);
atomic<int> callback_count{0};
int count = 10000;
{
std::thread cor_call([&]()
{
HelloPrx prx = getObj<HelloPrx>(c.get(), "HelloAdapter");
//发起远程调用
for (int j = 0; j < count; ++j)
{
HelloPrxCallbackPtr p = new ClientHelloCallback(TC_Common::now2us(), j, count, _buffer, callback_count);
prx->async_testHello(p, j, _buffer);
}
});
cor_call.join();
}
waitForFinish(callback_count, count);
// TC_Common::sleep(10);
// LOG_CONSOLE_DEBUG << _count << ", " << callback_count << endl;
ASSERT_TRUE(count == callback_count);
stopServer(server);
}

17
unit-test/rpc/test_auth.cpp Executable file
View File

@ -0,0 +1,17 @@
#include "hello_test.h"
TEST_F(HelloTest, authSyncServerCommunicator)
{
transServerCommunicator([&](Communicator *comm){
checkSync(comm, "AuthObjAdapter");
});
}
TEST_F(HelloTest, authASyncGlobalCommunicatorInCoroutine)
{
transInCoroutineServerCommunicator([&](Communicator *comm){
checkASync(comm, "AuthObjAdapter");
});
}

View File

@ -0,0 +1,309 @@
#include "hello_test.h"
#include "servant/CommunicatorEpoll.h"
TEST_F(HelloTest, testNotifyCommunicatorEpoll)
{
shared_ptr<Communicator> c = getCommunicator();
int netThread = TC_Common::strto<int>(c->getProperty("netthread"));
HelloServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) 0);
auto v1 = c->getAllCommunicatorEpoll();
ASSERT_TRUE(v1.size() == 0);
HelloPrx prx = getObj<HelloPrx>(c.get(), "HelloAdapter");
std::thread th1([&]()
{ checkSyncOnce(prx); });
TC_Common::msleep(100);
auto v2 = c->getAllCommunicatorEpoll();
//两个公有通信器
ASSERT_TRUE(v2.size() == (size_t)netThread);
std::thread th2([&]()
{ checkSyncOnce(prx); });
TC_Common::msleep(100);
auto v3 = c->getAllCommunicatorEpoll();
//通信器个数不变
ASSERT_TRUE(v3.size() == (size_t)netThread);
funcInCoroutine([&]()
{
checkSyncOnce(prx);
auto v4 = c->getAllCommunicatorEpoll();
//为设置协程的情况下, 仍然是两个通信器
ASSERT_TRUE(v4.size() == (size_t)netThread);
},
false);
funcInCoroutine([&]()
{
checkSyncOnce(prx);
auto v5 = c->getAllCommunicatorEpoll();
//设置了协程, 会增加一个私有协程网络通信器
ASSERT_TRUE(v5.size() == (size_t)(netThread + 1));
},
true);
auto v6 = c->getAllCommunicatorEpoll();
//之前的业务线程释放了, 会减少一个私有协程网络通信器
ASSERT_TRUE(v6.size() == (size_t)netThread);
funcInCoroutine([&]()
{
checkASyncOnce(prx);
//设置协程, 会增加一个私有网路通信器, 同时异步回调在私有网络通信器中
auto v7 = c->getAllCommunicatorEpoll();
ASSERT_TRUE(v7.size() == (size_t)(netThread + 1));
});
th1.join();
th2.join();
stopServer(server);
}
int getNotify(shared_ptr<Communicator> c)
{
if(c->getCommunicatorEpollNum() <= 0)
{
return 0;
}
auto n = c->getCommunicatorEpoll(0)->getNotify();
int sum = 0;
for(size_t i = 0; i< MAX_CLIENT_NOTIFYEVENT_NUM; i++)
{
if(n[i] != NULL)
{
++sum;
}
}
return sum;
}
//测试notify句柄不泄露!
TEST_F(HelloTest, testNotifyBussThreadQuitOnce)
{
shared_ptr<Communicator> c = getCommunicator();
HelloPrx prx = getObj<HelloPrx>(c.get(), "HelloAdapter");
HelloServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) 0);
//先把服务器端的强制都创建好
for (int i = 0; i < 20; i++)
{
checkSyncOnce(prx);
}
for (int i = 0; i < 3; i++)
{
size_t sp_count = ServantProxyThreadData::g_immortal->getList().size();
size_t notify_count = getNotify(c);
{
std::thread th1([&]()
{ checkSyncOnce(prx); });
th1.join();
}
TC_Common::msleep(10);
//私有线程数据释放了, 通知句柄数不增加
ASSERT_TRUE(ServantProxyThreadData::g_immortal->getList().size() == sp_count);
ASSERT_TRUE(getNotify(c) == (int)notify_count);
}
stopServer(server);
}
//测试notify句柄不泄露!
TEST_F(HelloTest, testNotifyBussThreadQuit)
{
shared_ptr<Communicator> c = getCommunicator();
HelloPrx prx = getObj<HelloPrx>(c.get(), "HelloAdapter");
HelloServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) 0);
// for(int i = 0; i < 5000; i++)
for(int i = 0; i < 1000; i++)
{
{
std::thread th1([&]()
{
checkSyncOnce(prx);
});
th1.join();
}
TC_Common::msleep(10);
int num = getNotify(c);
ASSERT_TRUE(num < 5);
}
stopServer(server);
}
//
//TEST_F(HelloTest, testNotifyCommunicatorQuit)
//{
// HelloServer server;
// startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) 0);
//
// for(int i = 0; i < 1000; i++)
// {
// shared_ptr<Communicator> c = getCommunicator();
// HelloPrx prx = getObj<HelloPrx>(c.get(), "HelloAdapter");
//
// {
//
// std::thread th1([&]()
// {
// try
// {
// checkSyncOnce(prx);
// }
// catch(exception &ex)
// {
// LOG_CONSOLE_DEBUG << i << ", " << ex.what() << endl;
// }
//
// c.reset();
// });
//
// th1.join();
// }
//
// }
//
// stopServer(server);
//
//}
TEST_F(HelloTest, testNotifyProxyQuit)
{
HelloServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE)0);
shared_ptr<Communicator> c = getCommunicator();
HelloPrx prx = getObj<HelloPrx>(c.get(), "HelloAdapter");
int count = 10;
while (count-- > 0)
{
vector<std::thread*> vt;
for (int i = 0; i < 1; i++)
{
vt.push_back(new std::thread([&]()
{
checkSyncOnce(prx);
}));
}
for (auto v: vt)
{
v->join();
delete v;
}
// TC_Common::sleep(3);
}
stopServer(server);
}
TEST_F(HelloTest, testCommunicatorGetResourcesInfo)
{
HelloServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE)0);
shared_ptr<Communicator> c = getCommunicator();
HelloPrx prx = getObj<HelloPrx>(c.get(), "HelloAdapter");
int count = 10;
while (count-- > 0)
{
vector<std::thread*> vt;
for (int i = 0; i < 1; i++)
{
vt.push_back(new std::thread([&]()
{
checkSyncOnce(prx);
}));
}
for (auto v: vt)
{
v->join();
delete v;
}
}
string buf = c->getResourcesInfo();
LOG_CONSOLE_DEBUG << buf << endl;
stopServer(server);
}
#if 0
TEST_F(HelloTest, testNotifyCtrlC)
{
std::thread th([](){
TC_Common::sleep(2);
kill(getpid(), SIGINT);
});
HelloServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) 0);
HelloPrx prx = getObj<HelloPrx>(server.getCommunicator(), "HelloAdapter");
for(int i = 0; i < 10000; i++)
{
checkSyncOnce(prx);
}
stopServer(server);
}
TEST_F(HelloTest, testNotifyCtrlCGlobalCommunicator)
{
std::thread th([](){
TC_Common::sleep(2);
kill(getpid(), SIGINT);
});
shared_ptr<Communicator> c = std::make_shared<Communicator>();
HelloServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) 0);
for(int i = 0; i < 10000; i++)
{
checkSync(c.get());
}
stopServer(server);
}
#endif

20
unit-test/rpc/test_custom.cpp Executable file
View File

@ -0,0 +1,20 @@
#include "hello_test.h"
TEST_F(HelloTest, customSyncGlobalCommunicator)
{
shared_ptr<Communicator> c = getCommunicator();
transGlobalCommunicator([&](Communicator *comm){
syncCustom(comm);
}, c.get());
}
TEST_F(HelloTest, customASyncGlobalCommunicatorInCoroutine)
{
shared_ptr<Communicator> c = getCommunicator();
transInCoroutineGlobalCommunicator([&](Communicator *comm){
asyncCustom(comm);
}, c.get());
}

145
unit-test/rpc/test_dyeing.cpp Executable file
View File

@ -0,0 +1,145 @@
/**
* Tencent is pleased to support the open source community by making Tars available.
*
* Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
#include "hello_test.h"
#include "servant/AdminF.h"
#include "server/FrameworkServer.h"
#include "server/framework/DbHandle.h"
#define DYEFILEPATH (string("tars_dyeing") + FILE_SEP)
//被动染色测试,对接口调用进行染色。被动染色分为两步:
//1.通过管理接口设置染色字段的key值
//2.通过key值调用接口
#define N 1024
int getFileLine(const char *fileName)
{
ifstream infile(fileName);
char str[N];
int n=0;
while(!infile.eof())
{
infile.getline(str, sizeof(str));
string s = TC_Common::trim(str);
if(!s.empty())
{
n++;
}
}
return n;
}
//未打开染色开关的场景
TEST_F(HelloTest, DyeingNo)
{
HelloServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) 0);
HelloPrx prx = getObj<HelloPrx>(server.getCommunicator().get(), "HelloAdapter");
// int64_t tBegin = TC_TimeProvider::getInstance()->getNowMs();
// HelloPrx dyeingPrx= server.getCommunicator()->stringToProxy<HelloPrx>(DYEING_SERVANT_ENDPOINT);
string strIn="123456";
string strOut;
int ret=prx->testDyeing(strIn,strOut);
EXPECT_EQ(ret,0);
// TLOGDEBUG("no dyeing request time cost: "<< " | " << TC_TimeProvider::getInstance()->getNowMs() - tBegin << "(ms)" << endl);
stopServer(server);
}
//打开染色开关但未使用染色key调用的场景
TEST_F(HelloTest, DyeingNoKey)
{
FrameworkServer fs;
startServer(fs, FRAMEWORK_CONFIG());
CDbHandle::cleanEndPoint();
CDbHandle::addActiveEndPoint("TestApp.FrameworkServer.LogObj", 11005, 1);
HelloServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) 0);
// int64_t tBegin = TC_TimeProvider::getInstance()->getNowMs();
AdminFPrx adminFPrx = server.getCommunicator()->stringToProxy<AdminFPrx>("AdminObj@" + getLocalEndpoint(CONFIG()).toString());
// AdminFPrx adminFPrx = server.getCommunicator()->stringToProxy<AdminFPrx>(UNIT_TEST_ADMIN_NAME_ENDPOINT);
string setdyeing = adminFPrx->notify("tars.setdyeing 123456 TestApp.HelloServer.HelloObj testDyeing");
EXPECT_TRUE(setdyeing.find("DyeingKey=123456") != string::npos);
HelloPrx prx = getObj<HelloPrx>(server.getCommunicator().get(), "HelloAdapter");
// DyeingTestPrx dyeingPrx= server.getCommunicator()->stringToProxy<DyeingTestPrx>(DYEING_SERVANT_ENDPOINT);
string strIn="abc";
string strOut;
int ret=prx->testDyeing(strIn,strOut);
TC_Common::sleep(1);
EXPECT_EQ(ret,0);
// TLOGDEBUG("dyeing without key request time cost: "<< " | " << TC_TimeProvider::getInstance()->getNowMs() - tBegin << "(ms)" << endl);
stopServer(server);
stopServer(fs);
}
//打开染色开关使用染色key调用的场景
TEST_F(HelloTest, DyeingKey)
{
FrameworkServer fs;
startServer(fs, FRAMEWORK_CONFIG());
CDbHandle::cleanEndPoint();
CDbHandle::addActiveEndPoint("TestApp.FrameworkServer.LogObj", 11005, 1);
HelloServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) 0);
AdminFPrx adminFPrx = server.getCommunicator()->stringToProxy<AdminFPrx>("AdminObj@" + getLocalEndpoint(CONFIG()).toString());
string setdyeing = adminFPrx->notify("tars.setdyeing 123456 TestApp.HelloServer.HelloObj testDyeing");
EXPECT_TRUE(setdyeing.find("DyeingKey=123456") != string::npos);
TC_File::removeFile("./tars_dyeing", true);
HelloPrx prx = getObj<HelloPrx>(server.getCommunicator().get(), "HelloAdapter");
string strIn="123456";
string strOut;
int ret=prx->testDyeing(strIn,strOut);
TC_Common::sleep(1);
EXPECT_EQ(ret,0);
string dyeDayFile=DYEFILEPATH + "dyeing_" + TC_Common::nowdate2str() + ".log";
EXPECT_EQ(TC_File::isFileExist(dyeDayFile), true);
EXPECT_EQ(getFileLine(dyeDayFile.c_str()), 4);
string dyeDebugFile=DYEFILEPATH + "dyeing.log";
EXPECT_EQ(TC_File::isFileExist(dyeDebugFile), true);
EXPECT_EQ(getFileLine(dyeDebugFile.c_str()), 4);
stopServer(server);
stopServer(fs);
}

105
unit-test/rpc/test_http.cpp Executable file
View File

@ -0,0 +1,105 @@
#include "hello_test.h"
//
//TEST_F(HelloTest, sslSyncClient)
//{
// shared_ptr<Communicator> c = std::make_shared<Communicator>();
// TC_Config conf = CLIENT_CONFIG();
//
// c->setProperty(conf);
//
// try
// {
//
// HelloPrx prx = c->stringToProxy<HelloPrx>("TestApp.SSLServer.SSLObj@ssl -h 127.0.0.1 -p 9005 -t 10000");
// prx->tars_ping();
// LOG_CONSOLE_DEBUG << "prx succ" << endl;
//
// HelloPrx prx1 = c->stringToProxy<HelloPrx>("TestApp.SSLServer.SSL1Obj@ssl -h 127.0.0.1 -p 9006 -t 10000");
// prx1->tars_ping();
// LOG_CONSOLE_DEBUG << "prx1 succ" << endl;
//
// HelloPrx prx2 = c->stringToProxy<HelloPrx>("TestApp.SSLServer.SSL2Obj@ssl -h 127.0.0.1 -p 9007 -t 10000");
// prx2->tars_ping();
// LOG_CONSOLE_DEBUG << "prx2 succ" << endl;
//
// HelloPrx prx3 = c->stringToProxy<HelloPrx>("TestApp.SSLServer.SSL3Obj@ssl -h 127.0.0.1 -p 9008 -t 10000 -e 1");
// prx3->tars_ping();
// LOG_CONSOLE_DEBUG << "prx3 succ" << endl;
// }
// catch(exception &ex)
// {
// LOG_CONSOLE_DEBUG << ex.what() << endl;
// }
//
//}
TEST_F(HelloTest, httpSyncServerCommunicator)
{
transServerCommunicator([&](Communicator *comm){
checkSyncHttp(comm, "HttpAdapter", true);
checkSyncHttp(comm, "HttpAdapter", false);
});
}
TEST_F(HelloTest, httpSyncServerCommunicatorInCoroutine)
{
transInCoroutineServerCommunicator([&](Communicator *comm){
checkSyncHttp(comm, "HttpAdapter", true);
checkSyncHttp(comm, "HttpAdapter", false);
});
}
TEST_F(HelloTest, httpASyncServerCommunicator)
{
transServerCommunicator([&](Communicator *comm){
checkASyncHttp(comm, "HttpAdapter", true);
checkASyncHttp(comm, "HttpAdapter", false);
});
}
TEST_F(HelloTest, httpASyncServerCommunicatorInCoroutine)
{
transInCoroutineServerCommunicator([&](Communicator *comm){
checkASyncHttp(comm, "HttpAdapter", true);
checkASyncHttp(comm, "HttpAdapter", false);
});
}
#if TARS_SSL
TEST_F(HelloTest, httpsSyncServerCommunicator)
{
transServerCommunicator([&](Communicator *comm){
checkSyncHttp(comm, "HttpsAdapter", true);
checkSyncHttp(comm, "HttpsAdapter", false);
});
}
TEST_F(HelloTest, httpsSyncServerCommunicatorInCoroutine)
{
transInCoroutineServerCommunicator([&](Communicator *comm){
checkSyncHttp(comm, "HttpsAdapter", true);
checkSyncHttp(comm, "HttpsAdapter", false);
});
}
TEST_F(HelloTest, httpsASyncServerCommunicator)
{
transServerCommunicator([&](Communicator *comm){
checkASyncHttp(comm, "HttpsAdapter", true);
checkASyncHttp(comm, "HttpsAdapter", false);
});
}
TEST_F(HelloTest, httpsASyncServerCommunicatorInCoroutine)
{
transInCoroutineServerCommunicator([&](Communicator *comm){
checkASyncHttp(comm, "HttpsAdapter", true);
checkASyncHttp(comm, "HttpsAdapter", false);
});
}
#endif

View File

@ -0,0 +1,90 @@
#include "hello_test.h"
//#include "util/tc_socket_async.h"
TEST_F(HelloTest, proxyInvokeTimeout)
{
shared_ptr<Communicator> c = getCommunicator();
transGlobalCommunicator([&](Communicator *comm){
checkSyncTimeout(comm);
}, c.get());
transInCoroutineGlobalCommunicator([&](Communicator *comm){
checkSyncTimeout(comm);
}, c.get());
transServerCommunicator([&](Communicator *comm){
checkSyncTimeout(comm);
});
transInCoroutineServerCommunicator([&](Communicator *comm){
checkSyncTimeout(comm);
});
transAllocCommunicator([&](Communicator *comm){
checkSyncTimeout(comm);
});
transInCoroutineAllocCommunicator([&](Communicator *comm){
checkSyncTimeout(comm);
});
}
TEST_F(HelloTest, proxyAsyncInvokeTimeout)
{
shared_ptr<Communicator> c = getCommunicator();
transGlobalCommunicator([&](Communicator *comm){
checkASyncTimeout(comm);
}, c.get());
transInCoroutineGlobalCommunicator([&](Communicator *comm){
checkASyncTimeout(comm);
}, c.get());
transServerCommunicator([&](Communicator *comm){
checkASyncTimeout(comm);
});
transInCoroutineServerCommunicator([&](Communicator *comm){
checkASyncTimeout(comm);
});
transAllocCommunicator([&](Communicator *comm){
checkASyncTimeout(comm);
});
transInCoroutineAllocCommunicator([&](Communicator *comm){
checkASyncTimeout(comm);
});
}
TEST_F(HelloTest, proxyConnectionTimeout)
{
shared_ptr<Communicator> c = getCommunicator();
HelloPrx prx = c->stringToProxy<HelloPrx>("TestApp.HelloServer.HelloObj@tcp -h 111.111.111.11 -p 4444");
prx->tars_connect_timeout(5000);
prx->tars_set_timeout(20000);
prx->tars_async_timeout(30000);
int64_t t = TNOWMS;
bool connectError = false;
try
{
string out;
prx->testHello(0, "test", out);
}
catch(exception &ex)
{
connectError = true;
}
ASSERT_TRUE(connectError);
LOG_CONSOLE_DEBUG << TNOWMS - t << endl;
ASSERT_TRUE(TNOWMS - t >= 5000 && TNOWMS - t < 5050);
}

140
unit-test/rpc/test_prx_update.cpp Executable file
View File

@ -0,0 +1,140 @@
#include "hello_test.h"
#include "servant/CommunicatorEpoll.h"
#include "servant/ObjectProxy.h"
#include "server/framework/DbHandle.h"
#include "server/FrameworkServer.h"
#include "QueryF.h"
TEST_F(HelloTest, prxUpdate)
{
shared_ptr<Communicator> comm = getCommunicator();
RpcServer rpc1Server;
startServer(rpc1Server, RPC1_CONFIG());
RpcServer rpc2Server;
startServer(rpc2Server, RPC2_CONFIG());
HelloPrx qPrx = comm->stringToProxy<HelloPrx>("TestApp.RpcServer.HelloObj@tcp -h 127.0.0.1 -p 9990:tcp -h 127.0.0.1 -p 9991");
int ret;
string out;
ret = qPrx->testHello(0, _buffer, out);
ASSERT_TRUE(ret == 0);
ASSERT_TRUE(out == _buffer);
set<EndpointInfo> active;
active.insert(EndpointInfo(TC_Endpoint("tcp -h 127.0.0.1 -p 9992")));
set<EndpointInfo> inactive;
inactive.insert(EndpointInfo(TC_Endpoint("tcp -h 127.0.0.1 -p 9990")));
inactive.insert(EndpointInfo(TC_Endpoint("tcp -h 127.0.0.1 -p 9991")));
qPrx->tars_update_endpoints(active, inactive);
stopServer(rpc1Server);
stopServer(rpc2Server);
RpcServer rpc3Server;
startServer(rpc3Server, RPC3_CONFIG());
ret = qPrx->testHello(0, _buffer, out);
ASSERT_TRUE(ret == 0);
ASSERT_TRUE(out == _buffer);
stopServer(rpc3Server);
}
TEST_F(HelloTest, prxUpdateInCoroutine1)
{
shared_ptr<Communicator> comm = getCommunicator();
RpcServer rpc1Server;
startServer(rpc1Server, RPC1_CONFIG());
RpcServer rpc2Server;
startServer(rpc2Server, RPC2_CONFIG());
int ret;
string out;
HelloPrx qPrx;
funcInCoroutine([&](){
qPrx = comm->stringToProxy<HelloPrx>("TestApp.RpcServer.HelloObj@tcp -h 127.0.0.1 -p 9990:tcp -h 127.0.0.1 -p 9991");
ret = qPrx->testHello(0, _buffer, out);
ASSERT_TRUE(ret == 0);
ASSERT_TRUE(out == _buffer);
});
set<EndpointInfo> active;
active.insert(EndpointInfo(TC_Endpoint("tcp -h 127.0.0.1 -p 9992")));
set<EndpointInfo> inactive;
inactive.insert(EndpointInfo(TC_Endpoint("tcp -h 127.0.0.1 -p 9990")));
inactive.insert(EndpointInfo(TC_Endpoint("tcp -h 127.0.0.1 -p 9991")));
qPrx->tars_update_endpoints(active, inactive);
stopServer(rpc1Server);
stopServer(rpc2Server);
RpcServer rpc3Server;
startServer(rpc3Server, RPC3_CONFIG());
ret = qPrx->testHello(0, _buffer, out);
ASSERT_TRUE(ret == 0);
ASSERT_TRUE(out == _buffer);
stopServer(rpc3Server);
}
TEST_F(HelloTest, prxUpdateInCoroutine2)
{
shared_ptr<Communicator> comm = getCommunicator();
RpcServer rpc1Server;
startServer(rpc1Server, RPC1_CONFIG());
RpcServer rpc2Server;
startServer(rpc2Server, RPC2_CONFIG());
int ret;
string out;
HelloPrx qPrx;
funcInCoroutine([&](){
qPrx = comm->stringToProxy<HelloPrx>("TestApp.RpcServer.HelloObj@tcp -h 127.0.0.1 -p 9990:tcp -h 127.0.0.1 -p 9991");
ret = qPrx->testHello(0, _buffer, out);
ASSERT_TRUE(ret == 0);
ASSERT_TRUE(out == _buffer);
}, true);
funcInCoroutine([&]()
{
set<EndpointInfo> active;
active.insert(EndpointInfo(TC_Endpoint("tcp -h 127.0.0.1 -p 9992")));
set<EndpointInfo> inactive;
inactive.insert(EndpointInfo(TC_Endpoint("tcp -h 127.0.0.1 -p 9990")));
inactive.insert(EndpointInfo(TC_Endpoint("tcp -h 127.0.0.1 -p 9991")));
qPrx->tars_update_endpoints(active, inactive);
}, true);
stopServer(rpc1Server);
stopServer(rpc2Server);
RpcServer rpc3Server;
startServer(rpc3Server, RPC3_CONFIG());
ret = qPrx->testHello(0, _buffer, out);
ASSERT_TRUE(ret == 0);
ASSERT_TRUE(out == _buffer);
stopServer(rpc3Server);
}

30
unit-test/rpc/test_push.cpp Executable file
View File

@ -0,0 +1,30 @@
#include "hello_test.h"
TEST_F(HelloTest, pushSyncGlobalCommunicator)
{
shared_ptr<Communicator> c = getCommunicator();
transGlobalCommunicator([&](Communicator *comm){
testPush(comm);
}, c.get());
}
TEST_F(HelloTest, pushSyncGlobalCommunicatorInCoroutine)
{
shared_ptr<Communicator> c = getCommunicator();
transInCoroutineGlobalCommunicator([&](Communicator *comm){
testPush(comm);
}, c.get());
}
TEST_F(HelloTest, pushReconnectGlobalCommunicator)
{
shared_ptr<Communicator> c = getCommunicator();
transGlobalCommunicator([&](Communicator *comm){
testReconnect(comm);
}, c.get());
}

452
unit-test/rpc/test_registry.cpp Executable file
View File

@ -0,0 +1,452 @@
#include "hello_test.h"
#include "servant/CommunicatorEpoll.h"
#include "servant/ObjectProxy.h"
#include "server/framework/DbHandle.h"
#include "server/FrameworkServer.h"
#include "QueryF.h"
TEST_F(HelloTest, registryQuery)
{
shared_ptr<Communicator> c = getCommunicator();
TC_Config conf = CLIENT_CONFIG();
// conf.parseString(CLIENT_CONFIG);
c->setProperty(conf);
TC_Config fconf = FRAMEWORK_CONFIG();
CDbHandle::cleanEndPoint();
CDbHandle::addActiveEndPoint("TestApp.RpcServer.HelloObj", 9990, 1);
CDbHandle::addActiveEndPoint("TestApp.RpcServer.HelloObj", 9991, 1);
FrameworkServer fs;
startServer(fs, FRAMEWORK_CONFIG());
string obj = getObj(fconf, "RegistryAdapter");
QueryFPrx qPrx = c->stringToProxy<QueryFPrx>(obj);
{
std::vector<EndpointF> endpoints = qPrx->findObjectById("TestApp.RpcServer.HelloObj");
ASSERT_TRUE(endpoints.size() == 2);
ASSERT_TRUE(endpoints[0].port == 9990);
ASSERT_TRUE(endpoints[1].port == 9991);
}
{
LOG_CONSOLE_DEBUG << "add TestApp.RpcServer.HelloObj 9992" << endl;
CDbHandle::addActiveEndPoint("TestApp.RpcServer.HelloObj", 9992, 1);
TC_Common::sleep(6);
qPrx->getEndpoint();
TC_Common::msleep(100);
{
std::vector<EndpointF> endpoints = qPrx->findObjectById("TestApp.RpcServer.HelloObj");
ASSERT_TRUE(endpoints.size() == 3);
ASSERT_TRUE(endpoints[0].port == 9990);
ASSERT_TRUE(endpoints[1].port == 9991);
ASSERT_TRUE(endpoints[2].port == 9992);
}
}
{
LOG_CONSOLE_DEBUG << "add TestApp.RpcServer.HelloObj 9993" << endl;
CDbHandle::addActiveEndPoint("TestApp.RpcServer.HelloObj", 9993, 1);
TC_Common::sleep(6);
qPrx->getEndpoint();
TC_Common::msleep(100);
{
std::vector<EndpointF> endpoints = qPrx->findObjectById("TestApp.RpcServer.HelloObj");
ASSERT_TRUE(endpoints.size() == 4);
ASSERT_TRUE(endpoints[0].port == 9990);
ASSERT_TRUE(endpoints[1].port == 9991);
ASSERT_TRUE(endpoints[2].port == 9992);
ASSERT_TRUE(endpoints[3].port == 9993);
}
}
stopServer(fs);
}
#define START_FRAMEWORK_SERVER_1_2 \
CDbHandle::cleanEndPoint(); \
CDbHandle::addActiveEndPoint("TestApp.RpcServer.HelloObj", 9990, 1); \
CDbHandle::addActiveEndPoint("TestApp.RpcServer.HelloObj", 9991, 1); \
FrameworkServer fs; \
startServer(fs, FRAMEWORK_CONFIG()); \
RpcServer rpc1Server; \
startServer(rpc1Server, RPC1_CONFIG()); \
RpcServer rpc2Server; \
startServer(rpc2Server, RPC2_CONFIG());
#define START_FRAMEWORK_HTTP_SERVER_1_2 \
CDbHandle::cleanEndPoint(); \
CDbHandle::addActiveEndPoint("TestApp.RpcServer.HttpObj", 8180, 1); \
CDbHandle::addActiveEndPoint("TestApp.RpcServer.HttpObj", 8181, 1); \
FrameworkServer fs; \
startServer(fs, FRAMEWORK_CONFIG()); \
RpcServer rpc1Server; \
startServer(rpc1Server, RPC1_CONFIG()); \
RpcServer rpc2Server; \
startServer(rpc2Server, RPC2_CONFIG());
#define STOP_FRAMEWORK_SERVER stopServer(fs);
#define HELLO_CALL {\
HelloPrx qPrx = comm->stringToProxy<HelloPrx>("TestApp.RpcServer.HelloObj"); \
int ret; \
string out; \
ret = qPrx->testHello(0, _buffer, out); \
ASSERT_TRUE(ret == 0); \
ASSERT_TRUE(out == _buffer); }
#define CHECK_REGISTRY_UPDATE {\
stopServer(rpc1Server); \
CDbHandle::cleanEndPoint(); \
CDbHandle::addActiveEndPoint("TestApp.RpcServer.HelloObj", 9992, 1); \
RpcServer rpc3Server; \
startServer(rpc3Server, RPC3_CONFIG()); \
wait(6000); \
HelloPrx qPrx = comm->stringToProxy<HelloPrx>("TestApp.RpcServer.HelloObj"); \
string out = ""; \
int ret = qPrx->testHello(0, _buffer, out); \
ASSERT_TRUE(ret == 0); \
ASSERT_TRUE(out == _buffer); \
stopServer(rpc2Server); \
wait(100); \
out = ""; \
ret = qPrx->testHello(0, _buffer, out); \
ASSERT_TRUE(ret == 0); \
ASSERT_TRUE(out == _buffer); \
stopServer(rpc3Server); }
#define CREATE_COR \
{ \
auto scheduler = TC_CoroutineScheduler::create(); \
ServantProxyThreadData::getData()->_sched = scheduler; \
scheduler->go([&]() \
{ \
{ HELLO_CALL; wait(6500); HELLO_CALL } \
}); \
scheduler->run(); \
}
#define HTTP_CALL {\
ServantPrx prx = comm->stringToProxy<ServantPrx>("TestApp.RpcServer.HttpObj"); \
prx->tars_set_protocol(ServantProxy::PROTOCOL_HTTP1, 5); \
string buff = _buffer + "-" + TC_Common::tostr(TC_Thread::CURRENT_THREADID()); \
shared_ptr<TC_HttpRequest> req = std::make_shared<TC_HttpRequest>(); \
req->setPostRequest("http://tars.com/hello", buff, true); \
req->setHeader("Connection", "close"); \
shared_ptr<TC_HttpResponse> rsp; \
int count = 10; \
while(count-- > 0) { prx->http_call("hello", req, rsp); } }
#define HTTP_CREATE_COR \
{ \
auto scheduler = TC_CoroutineScheduler::create(); \
ServantProxyThreadData::getData()->_sched = scheduler; \
scheduler->go([&]() \
{ \
{ HTTP_CALL; wait(6200); HTTP_CALL } \
}); \
scheduler->run(); \
}
TEST_F(HelloTest, registryRpc)
{
shared_ptr<Communicator> c = getCommunicator();
START_FRAMEWORK_SERVER_1_2
rpcFromRegistry(c.get());
funcInCoroutine([&](){
rpcFromRegistry(c.get());
});
funcInCoroutine([&](){
shared_ptr<Communicator> comm = getCommunicator();
rpcFromRegistry(comm.get());
});
stopServer(rpc1Server);
stopServer(rpc2Server);
stopServer(fs);
}
TEST_F(HelloTest, registryRpcUpdateList)
{
shared_ptr<Communicator> comm = getCommunicator();
comm->setProperty("refresh-endpoint-interval", "5000");
START_FRAMEWORK_SERVER_1_2
HELLO_CALL
CHECK_REGISTRY_UPDATE
STOP_FRAMEWORK_SERVER
}
TEST_F(HelloTest, registryRpcUpdateListInCoroutine1)
{
shared_ptr<Communicator> comm = getCommunicator();
comm->setProperty("refresh-endpoint-interval", "5000");
START_FRAMEWORK_SERVER_1_2
funcInCoroutine([&]()
{
HELLO_CALL
CHECK_REGISTRY_UPDATE
});
STOP_FRAMEWORK_SERVER
}
TEST_F(HelloTest, registryRpcUpdateListInCoroutine2)
{
shared_ptr<Communicator> comm = getCommunicator();
comm->setProperty("refresh-endpoint-interval", "5000");
START_FRAMEWORK_SERVER_1_2
HELLO_CALL
funcInCoroutine([&]()
{
CHECK_REGISTRY_UPDATE
});
STOP_FRAMEWORK_SERVER
}
TEST_F(HelloTest, registryRpcCheckUpdateList)
{
shared_ptr<Communicator> comm = getCommunicator();
comm->setProperty("refresh-endpoint-interval", "5000");
START_FRAMEWORK_SERVER_1_2
//发起网路调用
HELLO_CALL
HELLO_CALL
//构建多个线程, 都完成hello的调用
std::thread cor1([&]()
{
CREATE_COR
});
std::thread cor2([&]()
{
CREATE_COR
});
std::thread cor3([&]()
{
CREATE_COR
});
TC_Common::msleep(200);
vector<shared_ptr<CommunicatorEpoll>> v = comm->getAllCommunicatorEpoll();
//5个网络通信器(2个公有, 3个私有)
ASSERT_TRUE(v.size() == 5);
ASSERT_FALSE(v[0]->isSchedCommunicatorEpoll());
ASSERT_FALSE(v[1]->isSchedCommunicatorEpoll());
ASSERT_TRUE(v[2]->isSchedCommunicatorEpoll());
ASSERT_TRUE(v[3]->isSchedCommunicatorEpoll());
ASSERT_TRUE(v[4]->isSchedCommunicatorEpoll());
vector<ObjectProxy*> vop;
for (auto ce : v)
{
ObjectProxy* op = ce->hasObjectProxy("TestApp.RpcServer.HelloObj");
if (op)
{
vop.push_back(op);
}
}
//网络通信器都有对象
ASSERT_TRUE(vop.size() == 5);
for (auto op : vop)
{
vector<AdapterProxy*> adapters = op->getAdapters();
// LOG_CONSOLE_DEBUG << adapters.size() << endl;
// for(auto a : adapters)
// {
// LOG_CONSOLE_DEBUG << a->trans()->getConnectEndpoint().toString() << endl;
// }
ASSERT_TRUE(adapters.size() == 2);
ASSERT_TRUE(adapters[0]->trans()->getConnectEndpoint().getPort() == 9990);
ASSERT_TRUE(adapters[1]->trans()->getConnectEndpoint().getPort() == 9991);
}
stopServer(rpc1Server);
//更新主控ip list
CDbHandle::cleanEndPoint();
CDbHandle::addActiveEndPoint("TestApp.RpcServer.HelloObj", 9992, 1);
RpcServer rpc3Server;
startServer(rpc3Server, RPC3_CONFIG());
//等待主控更新时间
wait(6000);
//调用两次, 这样两个公有网路通信器都会更新ip list
HELLO_CALL
HELLO_CALL
stopServer(rpc2Server);
wait(1000);
for (auto op : vop)
{
vector<AdapterProxy*> adapters = op->getAdapters();
for(auto adapter : adapters)
{
// LOG_CONSOLE_DEBUG << "isSched:"<< op->getCommunicatorEpoll()->isSchedCommunicatorEpoll()
// << ", netThreadSeq:" << op->getCommunicatorEpoll()->getCommunicatorNetThreadSeq()
// << ", " << adapter->trans()->getConnectEndpoint().toString()
// << ", isActiveInReg:" << adapter->isActiveInReg() << endl;
if(adapter->trans()->getConnectEndpoint().getPort() == 9992)
{
ASSERT_TRUE(adapter->isActiveInReg());
}
else
{
ASSERT_FALSE(adapter->isActiveInReg());
}
}
}
//第三个服务也停掉
stopServer(rpc3Server);
cor1.detach();
cor2.detach();
cor3.detach();
STOP_FRAMEWORK_SERVER
}
TEST_F(HelloTest, registryHttpRpcCheckUpdateList)
{
shared_ptr<Communicator> comm = getCommunicator();
comm->setProperty("refresh-endpoint-interval", "5000");
START_FRAMEWORK_HTTP_SERVER_1_2
//发起网路调用
HTTP_CALL
//构建多个线程, 都完成hello的调用
std::thread cor1([&]()
{
//注意http call里面会wait一下在调用, 等待ip list更新
HTTP_CREATE_COR
});
TC_Common::msleep(200);
vector<shared_ptr<CommunicatorEpoll>> v = comm->getAllCommunicatorEpoll();
// for_each(v.begin(), v.end(), [](const shared_ptr<CommunicatorEpoll> &c){
// LOG_CONSOLE_DEBUG << c->getCommunicatorNetThreadSeq() << ", " << c->isSchedCommunicatorEpoll() << endl;
// });
//3个网络通信器(2个公有, 1个私有)
ASSERT_TRUE(v.size() == 3);
ASSERT_FALSE(v[0]->isSchedCommunicatorEpoll());
ASSERT_FALSE(v[1]->isSchedCommunicatorEpoll());
ASSERT_TRUE(v[2]->isSchedCommunicatorEpoll());
ServantPrx prx = comm->stringToProxy<ServantPrx>("TestApp.RpcServer.HttpObj"); \
vector<ObjectProxy*> vop = prx->getObjectProxys();
//并行连接数*网络通信器个数
ASSERT_TRUE(vop.size() == 5*v.size());
for (auto op : vop)
{
vector<AdapterProxy*> adapters = op->getAdapters();
// for_each(adapters.begin(), adapters.end(), [](AdapterProxy*ap){
// LOG_CONSOLE_DEBUG << ap->trans()->getConnectEndpoint().toString() << endl;
// });
// LOG_CONSOLE_DEBUG << op << ", -------------------------------------------------" << endl;
ASSERT_TRUE(adapters.size() == 2);
ASSERT_TRUE(adapters[0]->trans()->getConnectEndpoint().getPort() == 8180);
ASSERT_TRUE(adapters[1]->trans()->getConnectEndpoint().getPort() == 8181);
}
stopServer(rpc1Server);
//更新主控ip list
CDbHandle::cleanEndPoint();
CDbHandle::addActiveEndPoint("TestApp.RpcServer.HttpObj", 8182, 1);
RpcServer rpc3Server;
startServer(rpc3Server, RPC3_CONFIG());
//等待主控更新时间
wait(6000);
//调用, 触发ip list更新
HTTP_CALL
stopServer(rpc2Server);
wait(100);
stopServer(rpc3Server);
for (auto op : vop)
{
vector<AdapterProxy*> adapters = op->getAdapters();
for(auto adapter : adapters)
{
// LOG_CONSOLE_DEBUG << "isSched:"<< op->getCommunicatorEpoll()->isSchedCommunicatorEpoll()
// << ", netThreadSeq:" << op->getCommunicatorEpoll()->getCommunicatorNetThreadSeq()
// << ", " << adapter->trans()->getConnectEndpoint().toString()
// << ", isActiveInReg:" << adapter->isActiveInReg() << endl;
if(adapter->trans()->getConnectEndpoint().getPort() == 8182)
{
ASSERT_TRUE(adapter->isActiveInReg());
}
else
{
ASSERT_FALSE(adapter->isActiveInReg());
}
}
}
cor1.detach();
STOP_FRAMEWORK_SERVER
}

114
unit-test/rpc/test_rpc.cpp Executable file
View File

@ -0,0 +1,114 @@
#include "hello_test.h"
TEST_F(HelloTest, rpcSyncGlobalCommunicator)
{
{
shared_ptr<Communicator> c = getCommunicator();
transGlobalCommunicator([&](Communicator *comm){
checkSync(comm);
}, c.get());
}
TC_Common::sleep(10);
}
TEST_F(HelloTest, rpcSyncGlobalCommunicatorInCoroutine)
{
shared_ptr<Communicator> c = getCommunicator();
transInCoroutineGlobalCommunicator([&](Communicator *comm){
checkSync(comm);
}, c.get());
}
TEST_F(HelloTest, rpcSyncServerCommunicator)
{
transServerCommunicator([&](Communicator *comm){
checkSync(comm);
});
}
TEST_F(HelloTest, rpcSyncServerCommunicatorInCoroutine)
{
transInCoroutineServerCommunicator([&](Communicator *comm){
checkSync(comm);
});
}
TEST_F(HelloTest, rpcSyncAllocCommunicator)
{
transAllocCommunicator([&](Communicator *comm){
checkSync(comm);
});
}
TEST_F(HelloTest, rpcSyncAllocCommunicatorInCoroutine)
{
transInCoroutineAllocCommunicator([&](Communicator *comm){
checkSync(comm);
});
}
TEST_F(HelloTest, rpcSyncComplexCommunicator)
{
shared_ptr<Communicator> c = getCommunicator();
transComplexCommunicator([&](Communicator *comm){
checkSync(comm);
}, c.get());
transComplexCommunicator([&](Communicator *comm){
checkSync(comm);
}, c.get());
transComplexCommunicator([&](Communicator *comm){
checkSync(comm);
}, c.get());
transComplexCommunicator([&](Communicator *comm){
checkSync(comm);
}, c.get());
}
TEST_F(HelloTest, rpcSyncComplexCommunicatorInCoroutine)
{
shared_ptr<Communicator> c = getCommunicator();
transInCoroutineComplexCommunicator([&](Communicator *comm){
checkSync(comm);
}, c.get());
transInCoroutineComplexCommunicator([&](Communicator *comm){
checkSync(comm);
}, c.get());
transInCoroutineComplexCommunicator([&](Communicator *comm){
checkSync(comm);
}, c.get());
transInCoroutineComplexCommunicator([&](Communicator *comm){
checkSync(comm);
}, c.get());
}
TEST_F(HelloTest, rpcSyncIpV6GlobalCommunicator)
{
shared_ptr<Communicator> c = getCommunicator();
transGlobalCommunicator([&](Communicator *comm){
checkSync(comm, "Ipv6Adapter");
}, c.get());
}
TEST_F(HelloTest, rpcSyncIpV6GlobalCommunicatorInCoroutine)
{
shared_ptr<Communicator> c = getCommunicator();
transInCoroutineGlobalCommunicator([&](Communicator *comm){
checkSync(comm, "Ipv6Adapter");
}, c.get());
}

97
unit-test/rpc/test_ssl.cpp Executable file
View File

@ -0,0 +1,97 @@
#include "hello_test.h"
#if TARS_SSL
//
//TEST_F(HelloTest, sslSyncClient)
//{
// shared_ptr<Communicator> c = std::make_shared<Communicator>();
// TC_Config conf = CLIENT_CONFIG();
//
// c->setProperty(conf);
//
// try
// {
//
// HelloPrx prx = c->stringToProxy<HelloPrx>("TestApp.SSLServer.SSLObj@ssl -h 127.0.0.1 -p 9005 -t 10000");
// prx->tars_ping();
// LOG_CONSOLE_DEBUG << "prx succ" << endl;
//
// HelloPrx prx1 = c->stringToProxy<HelloPrx>("TestApp.SSLServer.SSL1Obj@ssl -h 127.0.0.1 -p 9006 -t 10000");
// prx1->tars_ping();
// LOG_CONSOLE_DEBUG << "prx1 succ" << endl;
//
// HelloPrx prx2 = c->stringToProxy<HelloPrx>("TestApp.SSLServer.SSL2Obj@ssl -h 127.0.0.1 -p 9007 -t 10000");
// prx2->tars_ping();
// LOG_CONSOLE_DEBUG << "prx2 succ" << endl;
//
// HelloPrx prx3 = c->stringToProxy<HelloPrx>("TestApp.SSLServer.SSL3Obj@ssl -h 127.0.0.1 -p 9008 -t 10000 -e 1");
// prx3->tars_ping();
// LOG_CONSOLE_DEBUG << "prx3 succ" << endl;
// }
// catch(exception &ex)
// {
// LOG_CONSOLE_DEBUG << ex.what() << endl;
// }
//
//}
TEST_F(HelloTest, sslSyncServerCommunicator)
{
transServerCommunicator([&](Communicator *comm){
checkSync(comm, "SSLHelloAdapter");
});
}
TEST_F(HelloTest, sslASyncServerCommunicatorInCoroutine)
{
transInCoroutineServerCommunicator([&](Communicator *comm){
checkASync(comm, "SSLHelloAdapter");
});
}
TEST_F(HelloTest, ssl1SyncServerCommunicator)
{
transServerCommunicator([&](Communicator *comm){
checkSync(comm, "SSLHello1Adapter");
});
}
TEST_F(HelloTest, ssl1ASyncServerCommunicatorInCoroutine)
{
transInCoroutineServerCommunicator([&](Communicator *comm){
checkASync(comm, "SSLHello1Adapter");
});
}
TEST_F(HelloTest, ssl2SyncServerCommunicator)
{
transServerCommunicator([&](Communicator *comm){
checkSync(comm, "SSLHello2Adapter");
});
}
TEST_F(HelloTest, ssl2ASyncServerCommunicatorInCoroutine)
{
transInCoroutineServerCommunicator([&](Communicator *comm){
checkASync(comm, "SSLHello2Adapter");
});
}
TEST_F(HelloTest, ssl3SyncServerCommunicator)
{
transServerCommunicator([&](Communicator *comm){
checkSync(comm, "SSLHello3Adapter");
});
}
TEST_F(HelloTest, ssl3ASyncServerCommunicatorInCoroutine)
{
transInCoroutineServerCommunicator([&](Communicator *comm){
checkASync(comm, "SSLHello3Adapter");
});
}
#endif

114
unit-test/rpc/test_stat.cpp Executable file
View File

@ -0,0 +1,114 @@
#include "hello_test.h"
#include "server/FrameworkServer.h"
int getStatCount(const vector<map<tars::StatMicMsgHead, tars::StatMicMsgBody>> &data)
{
LOG_CONSOLE_DEBUG << "client stat:" << data.size() << endl;
int sum = 0;
for_each(data.begin(), data.end(), [&](const map<tars::StatMicMsgHead, tars::StatMicMsgBody> &r){
for(auto e : r)
{
// LOG_CONSOLE_DEBUG << e.first.writeToJsonString() << ", " << e.second.writeToJsonString() << endl;
sum += e.second.count ;
}
});
return sum;
}
TEST_F(HelloTest, statReport)
{
FrameworkServer fs;
startServer(fs, FRAMEWORK_CONFIG());
HelloServer hs;
startServer(hs, CONFIG());
_clientStatData.clear();
shared_ptr<Communicator> c = getCommunicator();
int totalReport = 0;
int totalRealReport = 0;
int count = 3;
while(count-->0)
{
int report = rand() % 100;
if(report == 0)
{
continue;
}
checkStat(c.get(), report);
TC_Common::sleep(1);
totalReport += report;
totalRealReport = getStatCount(_clientStatData);
LOG_CONSOLE_DEBUG << "report:" << report << ", totalReport:" << totalReport << ", totalRealReport:" << totalRealReport << ", " << _clientStatData.size()<< endl;
ASSERT_TRUE(totalReport >= totalRealReport);
ASSERT_TRUE(totalReport - totalRealReport <= 20);
}
// LOG_CONSOLE_DEBUG << "client stat:" << _clientStatData.size() << endl;
// LOG_CONSOLE_DEBUG << "server stat:" << _serverStatData.size() << endl;
stopServer(hs);
stopServer(fs);
}
TEST_F(HelloTest, statReportInCoroutine)
{
FrameworkServer fs;
startServer(fs, FRAMEWORK_CONFIG());
HelloServer hs;
startServer(hs, CONFIG());
_clientStatData.clear();
shared_ptr<Communicator> c = getCommunicator();
funcInCoroutine([=]()
{
int totalReport = 0;
int totalRealReport = 0;
int count = 3;
while (count-- > 0)
{
int report = rand() % 100;
if (report == 0)
{
continue;
}
checkStat(c.get(), report);
TC_Common::sleep(1);
totalReport += report;
totalRealReport = getStatCount(_clientStatData);
LOG_CONSOLE_DEBUG << "report:" << report << ", totalReport:" << totalReport << ", totalRealReport:"
<< totalRealReport << ", data size:" << _clientStatData.size() << endl;
ASSERT_TRUE(totalReport >= totalRealReport);
ASSERT_TRUE(totalReport - totalRealReport <= 20);
}
}, true);
stopServer(hs);
stopServer(fs);
}

165
unit-test/rpc/test_trans.cpp Executable file
View File

@ -0,0 +1,165 @@
#include "hello_test.h"
TEST_F(HelloTest, rpcTransGlobalCommunicator)
{
shared_ptr<Communicator> c = getCommunicator();
transGlobalCommunicator([&](Communicator *comm){
checkTransSyncASync(comm);
}, c.get());
transGlobalCommunicator([&](Communicator *comm){
checkTransASyncASync(comm);
}, c.get());
transGlobalCommunicator([&](Communicator *comm){
checkTransSyncSync(comm);
}, c.get());
transGlobalCommunicator([&](Communicator *comm){
checkTransASyncSync(comm);
}, c.get());
}
TEST_F(HelloTest, rpcTransGlobalCommunicatorInCoroutine)
{
shared_ptr<Communicator> c = getCommunicator();
transInCoroutineGlobalCommunicator([&](Communicator *comm){
checkTransSyncASync(comm);
}, c.get());
transInCoroutineGlobalCommunicator([&](Communicator *comm){
checkTransASyncASync(comm);
}, c.get());
transInCoroutineGlobalCommunicator([&](Communicator *comm){
checkTransSyncSync(comm);
}, c.get());
transInCoroutineGlobalCommunicator([&](Communicator *comm){
checkTransASyncSync(comm);
}, c.get());
}
TEST_F(HelloTest, rpcTransServerCommunicator)
{
transServerCommunicator([&](Communicator *comm){
checkTransSyncASync(comm);
});
transServerCommunicator([&](Communicator *comm){
checkTransASyncASync(comm);
});
transServerCommunicator([&](Communicator *comm){
checkTransSyncSync(comm);
});
transServerCommunicator([&](Communicator *comm){
checkTransASyncSync(comm);
});
}
TEST_F(HelloTest, rpcTransServerCommunicatorInCoroutine)
{
transInCoroutineServerCommunicator([&](Communicator *comm){
checkTransSyncASync(comm);
});
transInCoroutineServerCommunicator([&](Communicator *comm){
checkTransASyncASync(comm);
});
transInCoroutineServerCommunicator([&](Communicator *comm){
checkTransSyncSync(comm);
});
transInCoroutineServerCommunicator([&](Communicator *comm){
checkTransASyncSync(comm);
});
}
TEST_F(HelloTest, rpcTransAllocCommunicator)
{
transAllocCommunicator([&](Communicator *comm){
checkTransSyncASync(comm);
});
transAllocCommunicator([&](Communicator *comm){
checkTransASyncASync(comm);
});
transAllocCommunicator([&](Communicator *comm){
checkTransSyncSync(comm);
});
transAllocCommunicator([&](Communicator *comm){
checkTransASyncSync(comm);
});
}
TEST_F(HelloTest, rpcTransAllocCommunicatorInCoroutine)
{
transInCoroutineAllocCommunicator([&](Communicator *comm){
checkTransSyncASync(comm);
});
transInCoroutineAllocCommunicator([&](Communicator *comm){
checkTransASyncASync(comm);
});
transInCoroutineAllocCommunicator([&](Communicator *comm){
checkTransSyncSync(comm);
});
transInCoroutineAllocCommunicator([&](Communicator *comm){
checkTransASyncSync(comm);
});
}
TEST_F(HelloTest, rpcTransComplexCommunicator)
{
shared_ptr<Communicator> c = getCommunicator();
transComplexCommunicator([&](Communicator *comm){
checkTransSyncASync(comm);
}, c.get());
transComplexCommunicator([&](Communicator *comm){
checkTransASyncASync(comm);
}, c.get());
transComplexCommunicator([&](Communicator *comm){
checkTransSyncSync(comm);
}, c.get());
transComplexCommunicator([&](Communicator *comm){
checkTransASyncSync(comm);
}, c.get());
}
TEST_F(HelloTest, rpcTransComplexCommunicatorInCoroutine)
{
shared_ptr<Communicator> c = getCommunicator();
transInCoroutineComplexCommunicator([&](Communicator *comm){
checkTransSyncASync(comm);
}, c.get());
transInCoroutineComplexCommunicator([&](Communicator *comm){
checkTransASyncASync(comm);
}, c.get());
transInCoroutineComplexCommunicator([&](Communicator *comm){
checkTransSyncSync(comm);
}, c.get());
transInCoroutineComplexCommunicator([&](Communicator *comm){
checkTransASyncSync(comm);
}, c.get());
}

68
unit-test/rpc/test_udp.cpp Executable file
View File

@ -0,0 +1,68 @@
#include "hello_test.h"
#define UDP_ASYNC_COUNT 100
TEST_F(HelloTest, udpSyncGlobalCommunicator)
{
shared_ptr<Communicator> c = getCommunicator();
transGlobalCommunicator([&](Communicator *comm){
checkSync(comm, "UdpObjAdapter");
}, c.get());
}
TEST_F(HelloTest, udpASyncGlobalCommunicator)
{
shared_ptr<Communicator> c = getCommunicator();
int count = _count;
_count = UDP_ASYNC_COUNT;
//异步udp, 发送太快了会丢包
transGlobalCommunicator([&](Communicator *comm){
checkASync(comm, "UdpObjAdapter");
}, c.get());
_count = count;
}
TEST_F(HelloTest, udpASyncGlobalCommunicatorInCoroutine)
{
shared_ptr<Communicator> c = getCommunicator();
int count = _count;
_count = UDP_ASYNC_COUNT;
transInCoroutineGlobalCommunicator([&](Communicator *comm){
checkASync(comm, "UdpObjAdapter");
}, c.get());
_count = count;
}
TEST_F(HelloTest, udpIpV6SyncGlobalCommunicator)
{
shared_ptr<Communicator> c = getCommunicator();
transGlobalCommunicator([&](Communicator *comm){
checkSync(comm, "UdpIpv6Adapter");
}, c.get());
}
TEST_F(HelloTest, udpIpV6ASyncGlobalCommunicatorInCoroutine)
{
shared_ptr<Communicator> c = getCommunicator();
int count = _count;
_count = UDP_ASYNC_COUNT;
transInCoroutineGlobalCommunicator([&](Communicator *comm){
checkASync(comm, "UdpIpv6Adapter");
}, c.get());
_count = count;
}

View File

@ -0,0 +1,261 @@
#include "hello_test.h"
#include "../server/WinServer.h"
TEST_F(HelloTest, winServerInCoroutine)
{
funcInCoroutine([&]()
{
auto comm = getCommunicator();
WinServer ws;
startServer(ws, WIN_CONFIG());
string obj = getObj(ws.getConfig(), "WinAdapter");
HelloPrx prx = comm->stringToProxy<HelloPrx>(obj);
string out;
prx->testHello(0, _buffer, out);
ASSERT_TRUE(_buffer == out);
stopServer(ws);
},
true);
}
TEST_F(HelloTest, winServerGlobalInCoroutine)
{
auto comm = getCommunicator();
WinServer ws;
startServer(ws, WIN_CONFIG());
string obj = getObj(ws.getConfig(), "WinAdapter");
{
std::thread cor_call([&]()
{
auto scheduler = TC_CoroutineScheduler::create();
//设置到协程中
ServantProxyThreadData::getData()->_sched = scheduler;
scheduler->go([&]()
{
scheduler->setNoCoroutineCallback([=](TC_CoroutineScheduler* s)
{
s->terminate();
});
HelloPrx prx = comm->stringToProxy<HelloPrx>(obj);
string out;
prx->testHello(0, _buffer, out);
ASSERT_TRUE(_buffer == out);
});
scheduler->run();
});
cor_call.join();
}
stopServer(ws);
}
TEST_F(HelloTest, winServer)
{
shared_ptr<Communicator> c = getCommunicator();
WinServer ws;
startServer(ws, WIN_CONFIG(), (TC_EpollServer::SERVER_OPEN_COROUTINE)0);
string obj = getObj(ws.getConfig(), "WinAdapter");
HelloPrx prx = c->stringToProxy<HelloPrx>(obj);
string out;
prx->testHello(0, _buffer, out);
stopServer(ws);
}
TEST_F(HelloTest, winServerAsync)
{
shared_ptr<Communicator> c = getCommunicator();
for(int i = 0; i <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; i++)
{
WinServer ws;
startServer(ws, WIN_CONFIG(), (TC_EpollServer::SERVER_OPEN_COROUTINE)i);
atomic<int> callback_count{ 0 };
string obj = getObj(ws.getConfig(), "WinAdapter");
HelloPrx prx = c->stringToProxy<HelloPrx>(obj);
//发起远程调用
for (int j = 0; j < _count; ++j)
{
HelloPrxCallbackPtr p = new ClientHelloCallback(TC_Common::now2us(), j, _count, _buffer,
callback_count);
prx->async_testHello(p, j, _buffer);
}
waitForFinish(callback_count, _count);
ASSERT_TRUE(callback_count == _count);
stopServer(ws);
}
}
TEST_F(HelloTest, winServerHandleDestroy)
{
int i = 1;//TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO;
for(i = 0; i <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; i++)
{
g_handleDestroy = 0;
WinServer ws;
startServer(ws, WIN_CONFIG(), (TC_EpollServer::SERVER_OPEN_COROUTINE) i);
string obj = getObj(ws.getConfig(), "WinAdapter");
HelloPrx prx = ws.getCommunicator()->stringToProxy<HelloPrx>(obj);
string out;
prx->testHello(0, _buffer, out);
ASSERT_TRUE(_buffer == out);
stopServer(ws);
ASSERT_TRUE(g_handleDestroy == TC_Common::strto<int>(ws.getConfig().get("/tars/application/server/WinAdapter<threads>")));
}
}
TEST_F(HelloTest, winServerFdLeak)
{
int i = 0;
//先跑一边, 把需要分配的句柄都分配完
for (i = 0; i <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; i++)
{
WinServer ws;
startServer(ws, WIN_CONFIG(), (TC_EpollServer::SERVER_OPEN_COROUTINE)i);
string obj = getObj(ws.getConfig(), "WinAdapter");
HelloPrx prx = ws.getCommunicator()->stringToProxy<HelloPrx>(obj);
string out;
//网络通信器有多个, 就要调用多次
prx->testHello(0, _buffer, out);
ASSERT_TRUE(_buffer == out);
prx->testHello(0, _buffer, out);
ASSERT_TRUE(_buffer == out);
stopServer(ws);
}
//第二遍检查句柄是否泄漏
for (i = 0; i <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; i++)
{
int ofdCount = getFdCounts();
{
WinServer ws;
startServer(ws, WIN_CONFIG(), (TC_EpollServer::SERVER_OPEN_COROUTINE)i);
string obj = getObj(ws.getConfig(), "WinAdapter");
HelloPrx prx = ws.getCommunicator()->stringToProxy<HelloPrx>(obj);
string out;
//网络通信器有多个, 就要调用多次
prx->testHello(0, _buffer, out);
ASSERT_TRUE(_buffer == out);
prx->testHello(0, _buffer, out);
ASSERT_TRUE(_buffer == out);
stopServer(ws);
}
// TC_Common::sleep(1000);
int nfdCount = getFdCounts();
//linux下才有效
LOG_CONSOLE_DEBUG << "old fd count:" << ofdCount << ", new fd count:" << nfdCount << endl;
// ASSERT_TRUE(ofdCount == nfdCount);
}
}
TEST_F(HelloTest, winServerRestart)
{
int i = 0;//TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO;
for(i = 0; i <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; i++)
{
WinServer ws;
int count = 10;
while(count-->0)
{
startServer(ws, WIN_CONFIG(), (TC_EpollServer::SERVER_OPEN_COROUTINE)i);
string obj = getObj(ws.getConfig(), "WinAdapter");
HelloPrx prx = ws.getCommunicator()->stringToProxy<HelloPrx>(obj);
string out;
prx->testHello(0, _buffer, out);
ASSERT_TRUE(_buffer == out);
stopServer(ws);
}
}
}
TEST_F(HelloTest, winLog)
{
WinServer ws;
startServer(ws, WIN_CONFIG());
string log1 = ServerConfig::Application + FILE_SEP + ServerConfig::ServerName + FILE_SEP + ServerConfig::Application + "." + ServerConfig::ServerName + ".test1.log";
string log2 = ServerConfig::Application + FILE_SEP + ServerConfig::ServerName + FILE_SEP + ServerConfig::Application + "." + ServerConfig::ServerName + ".test2.log";
TC_File::removeFile(log1, false);
TC_File::removeFile(log2, false);
ASSERT_TRUE(!TC_File::isFileExist(log1));
ASSERT_TRUE(!TC_File::isFileExist(log2));
TLOGEXDEBUG("test1", "test log"<< endl);
TLOGEXDEBUG("test2", "test log"<< endl);
LOG_CONSOLE_DEBUG << log1 << endl;
ASSERT_TRUE(TC_File::isFileExist(log1));
ASSERT_TRUE(TC_File::isFileExist(log2));
stopServer(ws);
}

9
unit-test/rpc/test_wup.cpp Executable file
View File

@ -0,0 +1,9 @@
#include "hello_test.h"
TEST_F(HelloTest, wupSync)
{
forEach([&](){
checkWup();
});
}

View File

@ -0,0 +1,70 @@
#include "hello_test.h"
TEST_F(HelloTest, rpcWupTransGlobalCommunicator)
{
shared_ptr<Communicator> c = getCommunicator();
transGlobalCommunicator([&](Communicator *comm){
checkWupTransSync(comm);
}, c.get());
}
TEST_F(HelloTest, rpcWupTransGlobalCommunicatorInCoroutine)
{
shared_ptr<Communicator> c = getCommunicator();
transInCoroutineGlobalCommunicator([&](Communicator *comm){
checkWupTransSync(comm);
}, c.get());
}
TEST_F(HelloTest, rpcWupTransServerCommunicator)
{
transServerCommunicator([&](Communicator *comm){
checkWupTransSync(comm);
});
}
TEST_F(HelloTest, rpcWupTransServerCommunicatorInCoroutine)
{
transInCoroutineServerCommunicator([&](Communicator *comm){
checkWupTransSync(comm);
});
}
TEST_F(HelloTest, rpcWupTransAllocCommunicator)
{
transAllocCommunicator([&](Communicator *comm){
checkWupTransSync(comm);
});
}
TEST_F(HelloTest, rpcWupTransAllocCommunicatorInCoroutine)
{
transInCoroutineAllocCommunicator([&](Communicator *comm){
checkWupTransSync(comm);
});
}
TEST_F(HelloTest, rpcWupTransComplexCommunicator)
{
shared_ptr<Communicator> c = getCommunicator();
transComplexCommunicator([&](Communicator *comm){
checkWupTransSync(comm);
}, c.get());
}
TEST_F(HelloTest, rpcWupTransComplexCommunicatorInCoroutine)
{
shared_ptr<Communicator> c = getCommunicator();
transInCoroutineComplexCommunicator([&](Communicator *comm){
checkWupTransSync(comm);
}, c.get());
}

View File

@ -0,0 +1,38 @@
#include "CustomImp.h"
#include "servant/Application.h"
using namespace std;
//////////////////////////////////////////////////////
void CustomImp::initialize()
{
//initialize servant here:
//...
}
//////////////////////////////////////////////////////
void CustomImp::destroy()
{
//destroy servant here:
//...
}
int CustomImp::doRequest(tars::CurrentPtr current, vector<char>& response)
{
//Return to the data package requested by the client itself, that is, the original package return (4-byte length + 4-byte request + buffer)
const vector<char>& request = current->getRequestBuffer();
response = request;
// cout << "doRequest: requestId:" << current->getRequestId() << ", funcName:" << current->getFuncName() << endl;
return 0;
}
int CustomImp::doClose(CurrentPtr current)
{
LOG->debug() << "close ip: " << current->getIp() << endl;
return 0;
}

View File

@ -0,0 +1,37 @@
#ifndef _CustomServantImp_H_
#define _CustomServantImp_H_
#include "servant/Application.h"
//#include "CustomServant.h"
/**
*
*
*/
class CustomImp : public tars::Servant
{
public:
/**
*
*/
virtual ~CustomImp() {}
/**
*
*/
virtual void initialize();
/**
*
*/
virtual void destroy();
//overloading method of Servant::doRequest
int doRequest(tars::CurrentPtr current, vector<char>& response);
//overloading method of Servant::doClose
int doClose(tars::CurrentPtr current);
};
/////////////////////////////////////////////////////
#endif

View File

@ -0,0 +1,152 @@
#include "FrameworkServer.h"
#include "framework/ConfigImp.h"
#include "framework/QueryImp.h"
#include "framework/StatImp.h"
#include "framework/LogImp.h"
#include "HttpImp.h"
#include "HelloImp.h"
using namespace std;
vector<map<tars::StatMicMsgHead, tars::StatMicMsgBody>> _clientStatData;
vector<map<tars::StatMicMsgHead, tars::StatMicMsgBody>> _serverStatData;
FrameworkServer::~FrameworkServer()
{
}
void
FrameworkServer::initialize()
{
addServant<ConfigImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".ConfigObj");
addServant<QueryImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".QueryObj");
addServant<StatImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".StatObj");
addServant<LogImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".LogObj");
string s;
loadLogFormat("","",s);
//日志路径
g_globe._log_path = _conf["/tars/log<logpath>"];
//启动写线程
g_globe._group.start(TC_Common::strto<size_t>(_conf["/tars/log<logthread>"]));
string prefix = TC_Common::lower(_conf.get("/tars/log<ipfix>","true"));
g_globe._bIpPrefix = (prefix == "true") ? true : false;
//增加对象
addServant<LogImp>(ServerConfig::Application + "." + ServerConfig::ServerName +".LogObj");
TARS_ADD_ADMIN_CMD_NORMAL("reloadLogFormat", FrameworkServer::loadLogFormat);
}
bool FrameworkServer::loadLogFormat(const string& command, const string& params, string& result)
{
TLOGDEBUG("FrameworkServer::loadLogFormat command:" << command << "|params:" << params << endl);
try
{
TC_Config conf;
conf.parseFile(ServerConfig::ConfigFile);
vector<string> vHourlist;
map<string,string> mLogType;
try
{
string sHour = conf["/tars/log/format<hour>"];
vHourlist = TC_Common::sepstr<string>(sHour,"|;,");
sort(vHourlist.begin(),vHourlist.end());
unique(vHourlist.begin(),vHourlist.end());
result = "loadLogFormat succ:" + sHour;
TLOGDEBUG("FrameworkServer::loadLogFormat result:" << result << endl);
DLOG<< "FrameworkServer::loadLogFormat result:" << result << endl;
//hour=app.server.file|app2.server2.file2
map<string,string> mType;
if(conf.getDomainMap("/tars/log/logtype", mType))
{
map<string,string>::iterator it = mType.begin();
while(it != mType.end())
{
vector<string> vList = TC_Common::sepstr<string>(it->second,"|;,");
for(size_t i = 0;i < vList.size();i++)
{
//app.server.file = hour
mLogType[vList[i]] = it->first;
TLOGDEBUG("FrameworkServer::loadLogFormat " << vList[i] << "|" << it->first << endl);
DLOG<<"FrameworkServer::loadLogFormat " << vList[i] << "|" << it->first << endl;
}
it++;
}
}
g_globe.update(vHourlist, mLogType);
}
catch(exception& e)
{
result += e.what();
TLOGERROR("FrameworkServer::loadLogFormat command:" << command << "|params:" << params << "|result:" << result << endl);
}
return true;
}
catch(exception &e)
{
result += e.what();
TLOGERROR("FrameworkServer::loadLogFormat command:" << command << "|params:" << params << "|result:" << result << endl);
}
return false;
}
void FrameworkServer::destroyApp()
{
}
void FrameworkServer::run()
{
this->waitForShutdown();
}
/////////////////////////////////////////////////////////////////
RpcServer::~RpcServer()
{
}
void
RpcServer::initialize()
{
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".HelloObj");
addServant<HttpImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".HttpObj");
addServantProtocol(ServerConfig::Application + "." + ServerConfig::ServerName + ".HttpObj", &TC_NetWorkBuffer::parseHttp);
}
/////////////////////////////////////////////////////////////////
void RpcServer::destroyApp()
{
}
void RpcServer::run()
{
this->waitForShutdown();
}

View File

@ -0,0 +1,62 @@
#ifndef _FrameworkServer_H_
#define _FrameworkServer_H_
#include <iostream>
#include "servant/Application.h"
using namespace tars;
extern vector<map<tars::StatMicMsgHead, tars::StatMicMsgBody>> _clientStatData;
extern vector<map<tars::StatMicMsgHead, tars::StatMicMsgBody>> _serverStatData;
class FrameworkServer : public Application, public TC_Thread
{
public:
/**
*
**/
virtual ~FrameworkServer();
/**
*
**/
virtual void initialize();
/**
*
**/
virtual void destroyApp();
protected:
virtual void run();
bool loadLogFormat(const string& command, const string& params, string& result);
};
class RpcServer : public Application, public TC_Thread
{
public:
/**
*
**/
virtual ~RpcServer();
/**
*
**/
virtual void initialize();
/**
*
**/
virtual void destroyApp();
protected:
virtual void run();
};
////////////////////////////////////////////
#endif

1520
unit-test/server/Hello.h Normal file

File diff suppressed because it is too large Load Diff

22
unit-test/server/Hello.tars Executable file
View File

@ -0,0 +1,22 @@
module Test
{
interface Hello
{
int testTrans(int index, string s, out string r);
int testSyncTrans(int index, string s, out string r);
int testHello(int index, string s, out string r);
int testPid(out string r);
int testTimeout(int timeout);
int testDyeing(routekey string strIn, out string strOut);
int testDyeingTrans();
};
};

145
unit-test/server/HelloImp.cpp Executable file
View File

@ -0,0 +1,145 @@
#include "HelloImp.h"
#include "HelloServer.h"
#include "servant/RemoteLogger.h"
using namespace tars;
std::atomic<int> hello_count(0);
std::atomic<int> trans_count(0);
HelloImp::HelloImp()
{
}
///////////////////////////////////////////////////////////////////////////////
void HelloImp::initialize()
{
Application::getCommunicator()->stringToProxy(g_HelloServerObj, _helloPrx);
_helloPrx->tars_async_timeout(100*1000);
}
void HelloImp::destroy()
{
++g_handleDestroy;
}
struct HelloCallback : public HelloPrxCallback
{
HelloCallback(tars::CurrentPtr &current, int index, const string &s) : _current(current), _index(index), _s(s)
{
}
//回调函数
virtual void callback_testHello(int ret, const string &r)
{
// LOG_CONSOLE_DEBUG << ret << endl;
assert(ret == 0);
Hello::async_response_testTrans(_current, ret, r);
}
virtual void callback_testHello_exception(tars::Int32 ret)
{
cout << "callback exception:" << ret << endl;
}
tars::CurrentPtr _current;
int _index;
string _s;
};
int HelloImp::testTrans(int index, const string &s, string &r, CurrentPtr current)
{
// LOG_CONSOLE_DEBUG << index << endl;
++trans_count;
try
{
current->setResponse(false);
HelloPrxCallbackPtr p = new HelloCallback(current, index, s);
_helloPrx->async_testHello(p, index, s);
}
catch (exception &e)
{
cout << "exception:" << e.what() << endl;
}
return 0;
}
int HelloImp::testSyncTrans(int index, const string &s, string &r, CurrentPtr current)
{
try
{
int ret = _helloPrx->testHello(index, s, r);
return ret;
}
catch (exception &e)
{
cout << "exception:" << e.what() << endl;
}
return -1;
}
int HelloImp::testHello(int index, const string& s, string& r, CurrentPtr current)
{
//
// if(index % 10000 == 0)
// {
// LOG_CONSOLE_DEBUG << index << endl;
// }
++hello_count;
r = s;
return 0;
}
int HelloImp::testPid(string &r, CurrentPtr current)
{
r = TC_Common::tostr(this->getApplication());
return 0;
}
int HelloImp::testTimeout(int timeout, CurrentPtr current)
{
TC_Common::sleep(timeout);
return 0;
}
int HelloImp::testDyeing(const std::string & strIn,std::string &strOut, CurrentPtr current)
{
LOG_CONSOLE_DEBUG << strIn << endl;
strOut="this is a dyeing message";
TLOG_DEBUG(strOut << "1, debug log" << endl);
FDLOG("test") << strOut << "1, day log" << endl;
TLOG_DEBUG(strOut << "2, debug log" << endl);
FDLOG("test") << strOut << "2, day log" << endl;
return _helloPrx->testDyeingTrans();
}
tars::Int32 HelloImp::testDyeingTrans(CurrentPtr current)
{
string strOut = "this is a dyeing trans message";
TLOG_DEBUG(strOut << "1, debug log" << endl);
FDLOG("test") << strOut << "1, day log" << endl;
TLOG_DEBUG(strOut << "2, debug log" << endl);
FDLOG("test") << strOut << "2, day log" << endl;
return 0;
}
///////////////////////////////////////////////////////////////////////////////

53
unit-test/server/HelloImp.h Executable file
View File

@ -0,0 +1,53 @@
#ifndef _HELLO_IMP_H_
#define _HELLO_IMP_H_
#include "Hello.h"
#include <map>
#include <string>
#include <vector>
using namespace std;
using namespace tars;
using namespace Test;
/////////////////////////////////////////////////////////////////////////
class HelloImp : public Hello {
public:
/**
*
*/
HelloImp();
public:
/**
*
*/
virtual void initialize();
/**
*
*/
virtual void destroy();
public:
int testTrans(int index, const string &s, string &r, CurrentPtr current);
int testSyncTrans(int index, const string &s, string &r, CurrentPtr current);
int testHello(int index, const string &s, string &r, CurrentPtr current);
int testPid(string &r, CurrentPtr current);
int testTimeout(int timeout, CurrentPtr current);
virtual tars::Int32 testDyeing(const std::string & strIn,std::string &strOut, CurrentPtr current);
virtual tars::Int32 testDyeingTrans(CurrentPtr current);
protected:
HelloPrx _helloPrx;
};
///////////////////////////////////////////////////////////////////////////////
#endif

118
unit-test/server/HelloServer.cpp Executable file
View File

@ -0,0 +1,118 @@
#include "HelloServer.h"
#include "HelloImp.h"
#include "TranImp.h"
#include "HttpImp.h"
#include "CustomImp.h"
#include "PushImp.h"
#include <thread>
// #include "gperftools/profiler.h"
using namespace std;
string g_HelloServerObj;
string g_TransDstServerObj;
atomic<int> g_handleDestroy = {0};
static TC_NetWorkBuffer::PACKET_TYPE parse(TC_NetWorkBuffer &in, vector<char> &out)
{
size_t len = sizeof(tars::Int32);
if (in.getBufferLength() < len)
{
return TC_NetWorkBuffer::PACKET_LESS;
}
string header;
in.getHeader(len, header);
assert(header.size() == len);
tars::Int32 iHeaderLen = 0;
::memcpy(&iHeaderLen, header.c_str(), sizeof(tars::Int32));
iHeaderLen = ntohl(iHeaderLen);
if (iHeaderLen > 100000 || iHeaderLen < (int)sizeof(unsigned int))
{
throw TarsDecodeException("packet length too long or too short,len:" + TC_Common::tostr(iHeaderLen));
}
if (in.getBufferLength() < (uint32_t)iHeaderLen)
{
return TC_NetWorkBuffer::PACKET_LESS;
}
in.getHeader(iHeaderLen, out);
in.moveHeader(iHeaderLen);
return TC_NetWorkBuffer::PACKET_FULL;
}
void
HelloServer::initialize()
{
g_HelloServerObj = ServerConfig::Application + "." + ServerConfig::ServerName +".HelloObj@" + getEpollServer()->getBindAdapter("HelloAdapter")->getEndpoint().toString();
g_TransDstServerObj = ServerConfig::Application + "." + ServerConfig::ServerName +".TransDstObj@" + getEpollServer()->getBindAdapter("TransDstAdapter")->getEndpoint().toString();
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName +".HelloObj");
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName +".TransObj");
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName +".HelloTimeoutObj");
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName +".HelloNoTimeoutObj");
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName +".Ipv6Obj");
addServant<HttpImp>(ServerConfig::Application + "." + ServerConfig::ServerName +".HttpObj");
addServantProtocol(ServerConfig::Application + "." + ServerConfig::ServerName + ".HttpObj", &TC_NetWorkBuffer::parseHttp);
addServant<HttpImp>(ServerConfig::Application + "." + ServerConfig::ServerName +".HttpsObj");
addServantProtocol(ServerConfig::Application + "." + ServerConfig::ServerName + ".HttpsObj", &TC_NetWorkBuffer::parseHttp);
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName +".TransDstObj");
addServant<TranImp>(ServerConfig::Application + "." + ServerConfig::ServerName +".TransWupObj");
//设置服务的协议解析器, 对服务器端而言, 解析器的目的就是识别包长度
//parseStream,表示第0个字节开始,类型是uint32_t, 字节序, 这个字段表示包的长度
TC_NetWorkBuffer::protocol_functor func = AppProtocol::parseStream<0, uint32_t, true>;
addServantProtocol(ServerConfig::Application + "." + ServerConfig::ServerName +".TransWupObj", func);
addServant<CustomImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".CustomObj");
addServantProtocol(ServerConfig::Application + "." + ServerConfig::ServerName + ".CustomObj", parse);
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".SSLObj");
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".SSL1Obj");
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".SSL2Obj");
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".SSL3Obj");
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".AuthObj");
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".UdpObj");
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".UdpIpv6Obj");
addServant<PushImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".PushObj");
addServantProtocol(ServerConfig::Application + "." + ServerConfig::ServerName + ".PushObj", parse);
pushThread = new PushInfoThread();
pushThread->start();
}
/////////////////////////////////////////////////////////////////
void HelloServer::destroyApp()
{
//destroy application here:
//...
if(pushThread)
{
pushThread->terminate();
pushThread->getThreadControl().join();
delete pushThread;
}
// LOG_CONSOLE_DEBUG << endl;
// ProfilerStop();
}
void HelloServer::run()
{
this->waitForShutdown();
}

39
unit-test/server/HelloServer.h Executable file
View File

@ -0,0 +1,39 @@
#ifndef __HelloServer_H_
#define __HelloServer_H_
#include <iostream>
#include "servant/Application.h"
#include "PushThread.h"
using namespace tars;
extern string g_HelloServerObj;
extern string g_TransDstServerObj;
extern atomic<int> g_handleDestroy;
class HelloServer : public Application, public TC_Thread
{
public:
HelloServer() {}
virtual ~HelloServer() {}
/**
*
**/
virtual void initialize();
/**
*
**/
virtual void destroyApp();
protected:
virtual void run();
private:
//用于push消息的线程
PushInfoThread *pushThread;
};
////////////////////////////////////////////
#endif

43
unit-test/server/HttpImp.cpp Executable file
View File

@ -0,0 +1,43 @@
#include "HttpImp.h"
//#include "HttpServer.h"
#include "servant/RemoteLogger.h"
#include "util/tc_http.h"
using namespace tars;
HttpImp::HttpImp()
{
}
int HttpImp::doRequest(tars::CurrentPtr current, vector<char>& response)
{
const vector<char>& request = current->getRequestBuffer();
// LOG_CONSOLE_DEBUG << string(request.data(), request.size()) << endl;
TC_HttpRequest req;
req.decode(request);
TC_HttpResponse rsp;
rsp.setResponse(200, "OK", req.getContent());
// rsp.setContentType("text/html;charset=utf-8");
// rsp.setConnection("close");
string buffer = rsp.encode();
// LOG_CONSOLE_DEBUG << buffer << endl;
current->sendResponse(buffer.c_str(), (uint32_t)buffer.length());
// current->close();
return 0;
}
void HttpImp::initialize()
{
}
void HttpImp::destroy()
{
}
///////////////////////////////////////////////////////////////////////////////

41
unit-test/server/HttpImp.h Executable file
View File

@ -0,0 +1,41 @@
#ifndef _HTTP_IMP_H_
#define _HTTP_IMP_H_
#include <map>
#include <string>
#include <vector>
#include "servant/Application.h"
using namespace std;
using namespace tars;
/////////////////////////////////////////////////////////////////////////
class HttpImp : public Servant {
public:
/**
*
*/
HttpImp();
public:
/**
*
*/
virtual void initialize();
/**
*
* @param current
* @param response
* @return int
*/
virtual int doRequest(tars::CurrentPtr current, vector<char> &response);
/**
*
*/
virtual void destroy();
};
///////////////////////////////////////////////////////////////////////////////
#endif

View File

@ -0,0 +1,56 @@
#include "PushImp.h"
#include "servant/Application.h"
#include "PushThread.h"
using namespace std;
//////////////////////////////////////////////////////
void PushImp::initialize()
{
//initialize servant here:
//...
}
//////////////////////////////////////////////////////
void PushImp::destroy()
{
//destroy servant here:
//...
}
int PushImp::doRequest(tars::CurrentPtr current, vector<char>& response)
{
// LOG_CONSOLE_DEBUG << endl;
//保存客户端的信息以便对客户端进行push消息
(PushUser::mapMutex).lock();
map<string, CurrentPtr>::iterator it = PushUser::pushUser.find(current->getIp());
if(it == PushUser::pushUser.end())
{
PushUser::pushUser.insert(map<string, CurrentPtr>::value_type(current->getIp(), current));
LOG->debug() << "connect ip: " << current->getIp() << endl;
}
(PushUser::mapMutex).unlock();
//返回给客户端它自己请求的数据包,即原包返回(4字节长度+4字节requestid+buffer)
const vector<char>& request = current->getRequestBuffer();
response = request;
return 0;
}
//客户端关闭到服务端的连接或者服务端发现客户端长时间未发送包过来然后超过60s就关闭连接
//调用的方法
int PushImp::doClose(CurrentPtr current)
{
(PushUser::mapMutex).lock();
map<string, CurrentPtr>::iterator it = PushUser::pushUser.find(current->getIp());
if(it != PushUser::pushUser.end())
{
PushUser::pushUser.erase(it);
LOG->debug() << "close ip: " << current->getIp() << endl;
}
(PushUser::mapMutex).unlock();
return 0;
}

View File

@ -0,0 +1,37 @@
#ifndef _PushImp_H_
#define _PushImp_H_
#include "servant/Application.h"
//#include "TestPushServant.h"
/**
*
*
*/
class PushImp : public tars::Servant
{
public:
/**
*
*/
virtual ~PushImp() {}
/**
*
*/
virtual void initialize();
/**
*
*/
virtual void destroy();
//重载Servant的doRequest方法
int doRequest(tars::CurrentPtr current, vector<char>& response);
//重载Servant的doClose方法
int doClose(tars::CurrentPtr current);
};
/////////////////////////////////////////////////////
#endif

View File

@ -0,0 +1,79 @@
#include "PushThread.h"
// #include <arpa/inet.h>
map<string, CurrentPtr> PushUser::pushUser;
TC_ThreadMutex PushUser::mapMutex;
PushInfoThread::~PushInfoThread()
{
PushUser::pushUser.clear();
}
void PushInfoThread::terminate(void)
{
tars::TC_ThreadLock::Lock sync(*this);
_bTerminate = true;
notifyAll();
}
void PushInfoThread::setPushInfo(const string &sInfo)
{
unsigned int iBuffLength = htonl(sInfo.size()+8);
unsigned char * pBuff = (unsigned char*)(&iBuffLength);
_sPushInfo = "";
for (int i = 0; i<4; ++i)
{
_sPushInfo += *pBuff++;
}
unsigned int iRequestId = htonl(_iId);
unsigned char * pRequestId = (unsigned char*)(&iRequestId);
for (int i = 0; i<4; ++i)
{
_sPushInfo += *pRequestId++;
}
_sPushInfo += sInfo;
}
//定期向客户push消息
void PushInfoThread::run(void)
{
setPushInfo("hello world");
int count = 0;
while (!_bTerminate)
{
++count;
if(count % 10 == 0)
{
(PushUser::mapMutex).lock();
for (map<string, CurrentPtr>::iterator it = (PushUser::pushUser).begin();
it != (PushUser::pushUser).end(); ++it) {
(it->second)->close();
LOG->debug() << "close" << endl;
}
(PushUser::mapMutex).unlock();
}
else
{
(PushUser::mapMutex).lock();
for (map<string, CurrentPtr>::iterator it = (PushUser::pushUser).begin();
it != (PushUser::pushUser).end(); ++it) {
(it->second)->sendResponse(_sPushInfo.c_str(), _sPushInfo.size());
LOG->debug() << "sendResponse: " << _sPushInfo.size() << endl;
}
(PushUser::mapMutex).unlock();
}
{
TC_ThreadLock::Lock sync(*this);
timedWait(1000);
}
}
}

View File

@ -0,0 +1,30 @@
#ifndef __PUSH_THREAD_H
#define __PUSH_THREAD_H
#include "servant/Application.h"
class PushUser
{
public:
static map<string, CurrentPtr> pushUser;
static TC_ThreadMutex mapMutex;
};
class PushInfoThread : public TC_Thread, public TC_ThreadLock
{
public:
PushInfoThread():_bTerminate(false),_iId(0){}
~PushInfoThread();
virtual void run();
void terminate();
void setPushInfo(const string &sInfo);
private:
bool _bTerminate;
unsigned int _iId;
string _sPushInfo;
};
#endif

69
unit-test/server/TranImp.cpp Executable file
View File

@ -0,0 +1,69 @@
#include "TranImp.h"
#include "HelloServer.h"
using namespace tars;
TranImp::TranImp()
{
}
///////////////////////////////////////////////////////////////////////////////
void TranImp::initialize()
{
Application::getCommunicator()->stringToProxy(g_TransDstServerObj, _servantPrx);
ProxyProtocol proto;
proto.requestFunc = ProxyProtocol::streamRequest;
proto.responseFunc = ProxyProtocol::tupResponse;
_servantPrx->tars_set_protocol(proto);
}
void TranImp::async_call(tars::CurrentPtr current, vector<char> &response)
{
const vector<char> &request = current->getRequestBuffer();
TarsInputStream<> is;
is.setBuffer(request.data(), request.size());
RequestPacket req;
req.readFrom(is);
ResponsePacket rsp;
TLOGDEBUG("async_call: begin remote call, req len:" << req.sBuffer.size() << endl);
/*a-sync-call*/
ServantProxyCallbackPtr cb = new ServantCallback("ServantCallback", this, current);
_servantPrx->rpc_call_async(req.iRequestId, req.sFuncName, request.data(), request.size(), cb);
current->setResponse(false);
}
std::atomic<int> wup_trans_count(0);
int TranImp::doRequest(tars::CurrentPtr current, vector<char> &response) {
++wup_trans_count;
async_call(current, response);
return 0;
}
int TranImp::doResponse(ReqMessagePtr resp) {
ServantCallback *cb = dynamic_cast<ServantCallback *>(resp->callback.get());
if (cb) {
vector<char> &buff = resp->response->sBuffer;
if (!buff.empty()) {
TLOGDEBUG("end remote call, req len:" << buff.size() << endl);
cb->getCurrent()->sendResponse(buff.data(), buff.size());
}
}
return 0;
}
void TranImp::destroy() {
}
///////////////////////////////////////////////////////////////////////////////

53
unit-test/server/TranImp.h Executable file
View File

@ -0,0 +1,53 @@
#ifndef _TRAN_IMP_H_
#define _TRAN_IMP_H_
#include <map>
#include <string>
#include <vector>
#include "servant/Application.h"
using namespace std;
using namespace tars;
/////////////////////////////////////////////////////////////////////////
class TranImp : public Servant {
public:
/**
*
*/
TranImp();
public:
/**
*
*/
virtual void initialize();
/**
*
* @param current
* @param response
* @return int
*/
virtual int doRequest(tars::CurrentPtr current, vector<char> &response);
/**
* @param resp
* @return int
*/
virtual int doResponse(ReqMessagePtr resp);
/**
*
*/
virtual void destroy();
protected:
void async_call(tars::CurrentPtr current, vector<char> &response);
protected:
ServantPrx _servantPrx;
};
///////////////////////////////////////////////////////////////////////////////
#endif

View File

@ -0,0 +1,49 @@
#include "WinServer.h"
#include "HelloImp.h"
#include "servant/Application.h"
using namespace std;
WinServer::~WinServer()
{
}
void
WinServer::initialize()
{
addServant<HelloImp>(ServerConfig::Application + "." + ServerConfig::ServerName + ".WinObj");
TARS_ADD_ADMIN_CMD_NORMAL("AdminCmdNormalTest", WinServer::cmdAdd);
TARS_ADD_ADMIN_CMD_NORMAL("CmdToDelete", WinServer::cmdAdd);
getNotifyObserver()->unregisterNotify("CmdToDelete", this);
TARS_ADD_ADMIN_CMD_NORMAL("DeletePrefixCmd", WinServer::delTarsViewVersion);
}
void WinServer::destroyApp()
{
}
void WinServer::run()
{
this->waitForShutdown();
}
bool WinServer::cmdAdd(const string& command, const string& params, string& result)
{
result = params + " AdminCmdNormalTest success!";
return true;
}
bool WinServer::delTarsViewVersion(const string& command, const string& params, string& result)
{
getNotifyObserver()->unregisterPrefix("tars.viewversion", this);
result = "Delete success!";
return true;
}

View File

@ -0,0 +1,37 @@
#ifndef _WinServer_H_
#define _WinServer_H_
#include <iostream>
#include "servant/Application.h"
using namespace tars;
class WinServer : public Application, public TC_Thread
{
public:
/**
*
**/
virtual ~WinServer();
/**
*
**/
virtual void initialize();
/**
*
**/
virtual void destroyApp();
bool cmdAdd(const string& command, const string& params, string& result);
bool delTarsViewVersion(const string& command, const string& params, string& result);
protected:
virtual void run();
};
////////////////////////////////////////////
#endif

72
unit-test/server/client.conf Executable file
View File

@ -0,0 +1,72 @@
<tars>
<application>
<client>
#tarsregistry locator
locator = TestApp.FrameworkServer.QueryObj@tcp -h 127.0.0.1 -p 11004
#max invoke timeout
sync-invoke-timeout = 50000
#refresh endpoint interval
refresh-endpoint-interval = 3000
#stat obj
stat = TestApp.FrameworkServer.StatObj@tcp -h 127.0.0.1 -p 12004
#max send queue length limit
sendqueuelimit = 1000000
#async queue length limit
asyncqueuecap = 1000000
#async callback thread num
asyncthread = 3
#net thread
netthread = 2
#merge net and sync thread
mergenetasync = 0
#module name
modulename = TestApp.SSLClient
#上报统计时间
report-interval = 10000
#server crt
ca = PROJECT_PATH/certs/server.crt
#can be empty
cert = PROJECT_PATH/certs/client.crt
#can be empty
key = PROJECT_PATH/certs/client.key
<TestApp.HelloServer.AuthObj>
#auth access key
accesskey = tars-test-user
#auth secret key
secretkey = 123456
</TestApp.HelloServer.AuthObj>
<TestApp.SSLServer.SSL1Obj>
#server crt
ca = PROJECT_PATH/certs/server1.crt
#can be empty
# cert = PROJECT_PATH/certs/client1.crt
#can be empty
# key = PROJECT_PATH/certs/client1.key
</TestApp.SSLServer.SSL1Obj>
<TestApp.SSLServer.SSL2Obj>
#server crt
ca = PROJECT_PATH/certs/server1.crt
#can be empty
cert = PROJECT_PATH/certs/client1.crt
#can be empty
key = PROJECT_PATH/certs/client1.key
</TestApp.SSLServer.SSL2Obj>
<TestApp.SSLServer.SSL3Obj>
#auth access key
accesskey = tars-test-user
#auth secret key
secretkey = 123456
#server crt
ca = PROJECT_PATH/certs/server1.crt
#can be empty
cert = PROJECT_PATH/certs/client1.crt
#can be empty
key = PROJECT_PATH/certs/client1.key
</TestApp.SSLServer.SSL3Obj>
</client>
</application>
</tars>

129
unit-test/server/framework.conf Executable file
View File

@ -0,0 +1,129 @@
<tars>
<application>
#proxy需要的配置
<client>
#地址
locator = TestApp.FrameworkServer.QueryObj@tcp -h 127.0.0.1 -p 11004
#最大超时时间(毫秒)
sync-invoke-timeout = 5000
async-invoke-timeout = 60000
#刷新端口时间间隔(毫秒)
refresh-endpoint-interval = 5000
#模块间调用[可选]
stat = TestApp.FrameworkServer.StatObj
#发送队列长度
sendqueuelimit = 1000000
#异步回调队列个数限制
asyncqueuecap = 1000000
#网络异步回调线程个数
asyncthread = 3
#网络线程个数
netthread = 2
#合并回调线程和网络线程(以网络线程个数为准)
mergenetasync = 0
#模块名称
modulename = TestApp.FrameworkServer
</client>
#定义所有绑定的IP
<server>
start_output = ERROR
closecout = 0
#应用名称
app = TestApp
#服务名称
server = FrameworkServer
#服务的数据目录,可执行文件,配置文件等
basepath = .
datapath = .
#日志路径
logpath = .
#网络线程个数
netthread = 1
#合并网络和业务线程(以网络线程个数为准)
mergenetimp = 0
opencoroutine = 0
loglevel=TARS
#本地管理套接字[可选]
local = tcp -h 127.0.0.1 -p 15701 -t 10000
#本地node的ip:port:timeout[可选]
# node = ServerObj@tcp -h 127.0.0.1 -p 2345 -t 10000
#配置中心的地址[可选]
config = TestApp.FrameworkServer.ConfigObj
#配置中心的地址[可选]
# notify = tars.tarsconfig.NotifyObj
#远程LogServer[可选]
log = TestApp.FrameworkServer.LogObj
<ConfigAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 11003 -t 60000
#allow ip
allow =
#max connection num
maxconns = 4096
#imp thread num
threads = 5
#servant
servant = TestApp.FrameworkServer.ConfigObj
#queue capacity
queuecap = 1000000
</ConfigAdapter>
<LogAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 11005 -t 60000
#allow ip
allow =
#max connection num
maxconns = 4096
#imp thread num
threads = 5
#servant
servant = TestApp.FrameworkServer.LogObj
#queue capacity
queuecap = 1000000
</LogAdapter>
<RegistryAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 11004 -t 60000
#allow ip
allow =
#max connection num
maxconns = 4096
#imp thread num
threads = 5
#servant
servant = TestApp.FrameworkServer.QueryObj
#queue capacity
queuecap = 1000000
</RegistryAdapter>
<StatAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 12004 -t 60000
#allow ip
allow =
#max connection num
maxconns = 4096
#imp thread num
threads = 5
#servant
servant = TestApp.FrameworkServer.StatObj
#queue capacity
queuecap = 1000000
</StatAdapter>
</server>
</application>
<log>
logpath = .
logthread = 1
ipfix = true
</log>
</tars>

View File

@ -0,0 +1,151 @@
#ifndef _CONFIGIMP_H_
#define _CONFIGIMP_H_
#include "servant/ConfigF.h"
#include "util/tc_file.h"
using namespace tars;
class ConfigImp : public Config
{
public:
/**
*
*/
ConfigImp(){};
/**
*
*/
virtual ~ConfigImp(){};
/**
*
*
* @return int
*/
virtual void initialize()
{
files["test.conf"] = "test-content";
};
/**
* 退
*/
virtual void destroy() {};
virtual int ListConfig(const string &app,const string &server, vector<string> &vf,tars::CurrentPtr current)
{
LOG_CONSOLE_DEBUG << app << ", " << server << endl;
return 0;
}
/**
*
* param app :
* param server: server名
* param filename:
*
* return :
*/
virtual int loadConfig(const std::string & app, const std::string & server, const std::string & filename, string &config, tars::CurrentPtr current)
{
LOG_CONSOLE_DEBUG << app << ", " << server << ", " << filename << endl;
map<string, string>::iterator it =files.find(filename);
if(it!=files.end()){
config = it->second;
}
return 0;
}
/**
* ip获取配置
* @param appServerName
* @param filename
* @param host
* @param config
*
* @return int
*/
virtual int loadConfigByHost(const string &appServerName, const string &filename, const string &host, string &config, tars::CurrentPtr current)
{
LOG_CONSOLE_DEBUG << appServerName << ", " << filename << ", " << host << endl;
return 0;
}
/**
*
* @param appServerName
* @param filename
* @param host
* @param current
*
* @return int
*/
virtual int checkConfig(const string &appServerName, const string &filename, const string &host, string &result, tars::CurrentPtr current)
{
LOG_CONSOLE_DEBUG << appServerName << ", " << filename << ", " << host << endl;
return 0;
}
/**
*
* param configInfo ConfigInfo
* param vf:
*
* return :
*/
virtual int ListConfigByInfo(const ConfigInfo& configInfo, vector<string> &vf,tars::CurrentPtr current)
{
LOG_CONSOLE_DEBUG << configInfo.writeToJsonString() << endl;
return 0;
}
/**
*
* param configInfo ConfigInfo
* param config:
*
* return :
*/
virtual int loadConfigByInfo(const ConfigInfo & configInfo, string &config,tars::CurrentPtr current)
{
LOG_CONSOLE_DEBUG << configInfo.writeToJsonString() << endl;
return 0;
}
/**
*
* @param configInfo ConfigInfo
*
* @return int
*/
virtual int checkConfigByInfo(const ConfigInfo & configInfo, string &result,tars::CurrentPtr current)
{
LOG_CONSOLE_DEBUG << configInfo.writeToJsonString() << endl;
return 0;
}
/**
*
* @param configInfo
* @param[out] vf
* @return int 0: , -1:
**/
virtual int ListAllConfigByInfo(const tars::GetConfigListInfo & configInfo, vector<std::string> &vf, tars::CurrentPtr current)
{
LOG_CONSOLE_DEBUG << configInfo.writeToJsonString() << endl;
return 0;
}
private:
map<string, string> files;
};
#endif /* TARS_TARS_TEST_TESTCODE_INCLUDE_STUB_CONFIGIMP_H_ */

View File

@ -0,0 +1,689 @@
#include <iterator>
#include <algorithm>
#include "DbHandle.h"
TC_ReadersWriterData<ObjectsCache> CDbHandle::_objectsCache;
TC_ReadersWriterData<CDbHandle::SetDivisionCache> CDbHandle::_setDivisionCache;
TC_ReadersWriterData<std::map<int, CDbHandle::GroupPriorityEntry> > CDbHandle::_mapGroupPriority;
//key-ip, value-组编号
TC_ReadersWriterData<map<string, int> > CDbHandle::_groupIdMap;
//key-group_name, value-组编号
TC_ReadersWriterData<map<string, int> > CDbHandle::_groupNameMap;
int CDbHandle::init(TC_Config *pconf)
{
return 0;
}
vector<EndpointF> CDbHandle::findObjectById(const string& id)
{
ObjectsCache::iterator it;
ObjectsCache& usingCache = _objectsCache.getReaderData();
if ((it = usingCache.find(id)) != usingCache.end())
{
return it->second.vActiveEndpoints;
}
else
{
vector<EndpointF> activeEp;
return activeEp;
}
}
int CDbHandle::findObjectById4All(const string& id, vector<EndpointF>& activeEp, vector<EndpointF>& inactiveEp)
{
TLOGDEBUG(__FUNCTION__ << " id: " << id << endl);
ObjectsCache::iterator it;
ObjectsCache& usingCache = _objectsCache.getReaderData();
if ((it = usingCache.find(id)) != usingCache.end())
{
activeEp = it->second.vActiveEndpoints;
inactiveEp = it->second.vInactiveEndpoints;
}
else
{
activeEp.clear();
inactiveEp.clear();
}
return 0;
}
vector<EndpointF> CDbHandle::getEpsByGroupId(const vector<EndpointF>& vecEps, const GroupUseSelect GroupSelect, int iGroupId, ostringstream& os)
{
os << "|";
vector<EndpointF> vResult;
for (unsigned i = 0; i < vecEps.size(); i++)
{
os << vecEps[i].host << ":" << vecEps[i].port << "(" << vecEps[i].groupworkid << ");";
if (GroupSelect == ENUM_USE_WORK_GROUPID && vecEps[i].groupworkid == iGroupId)
{
vResult.push_back(vecEps[i]);
}
if (GroupSelect == ENUM_USE_REAL_GROUPID && vecEps[i].grouprealid == iGroupId)
{
vResult.push_back(vecEps[i]);
}
}
return vResult;
}
vector<EndpointF> CDbHandle::getEpsByGroupId(const vector<EndpointF>& vecEps, const GroupUseSelect GroupSelect, const set<int>& setGroupID, ostringstream& os)
{
os << "|";
std::vector<EndpointF> vecResult;
for (std::vector<EndpointF>::size_type i = 0; i < vecEps.size(); i++)
{
os << vecEps[i].host << ":" << vecEps[i].port << "(" << vecEps[i].groupworkid << ")";
if (GroupSelect == ENUM_USE_WORK_GROUPID && setGroupID.count(vecEps[i].groupworkid) == 1)
{
vecResult.push_back(vecEps[i]);
}
if (GroupSelect == ENUM_USE_REAL_GROUPID && setGroupID.count(vecEps[i].grouprealid) == 1)
{
vecResult.push_back(vecEps[i]);
}
}
return vecResult;
}
int CDbHandle::findObjectByIdInSameGroup(const string& id, const string& ip, vector<EndpointF>& activeEp, vector<EndpointF>& inactiveEp, ostringstream& os)
{
activeEp.clear();
inactiveEp.clear();
int iClientGroupId = getGroupId(ip);
os << "|(" << iClientGroupId << ")";
if (iClientGroupId == -1)
{
return findObjectById4All(id, activeEp, inactiveEp);
}
ObjectsCache::iterator it;
ObjectsCache& usingCache = _objectsCache.getReaderData();
if ((it = usingCache.find(id)) != usingCache.end())
{
activeEp = getEpsByGroupId(it->second.vActiveEndpoints, ENUM_USE_WORK_GROUPID, iClientGroupId, os);
inactiveEp = getEpsByGroupId(it->second.vInactiveEndpoints, ENUM_USE_WORK_GROUPID, iClientGroupId, os);
if (activeEp.size() == 0) //没有同组的endpoit,匹配未启用分组的服务
{
activeEp = getEpsByGroupId(it->second.vActiveEndpoints, ENUM_USE_WORK_GROUPID, -1, os);
inactiveEp = getEpsByGroupId(it->second.vInactiveEndpoints, ENUM_USE_WORK_GROUPID, -1, os);
}
if (activeEp.size() == 0) //没有同组的endpoit
{
activeEp = it->second.vActiveEndpoints;
inactiveEp = it->second.vInactiveEndpoints;
}
}
return 0;
}
int CDbHandle::findObjectByIdInGroupPriority(const std::string& sID, const std::string& sIP, std::vector<EndpointF>& vecActive, std::vector<EndpointF>& vecInactive, std::ostringstream& os)
{
vecActive.clear();
vecInactive.clear();
int iClientGroupID = getGroupId(sIP);
os << "|(" << iClientGroupID << ")";
if (iClientGroupID == -1)
{
return findObjectById4All(sID, vecActive, vecInactive);
}
ObjectsCache& usingCache = _objectsCache.getReaderData();
ObjectsCache::iterator itObject = usingCache.find(sID);
if (itObject == usingCache.end()) return 0;
//首先在同组中查找
{
vecActive = getEpsByGroupId(itObject->second.vActiveEndpoints, ENUM_USE_WORK_GROUPID, iClientGroupID, os);
vecInactive = getEpsByGroupId(itObject->second.vInactiveEndpoints, ENUM_USE_WORK_GROUPID, iClientGroupID, os);
os << "|(In Same Group: " << iClientGroupID << " Active=" << vecActive.size() << " Inactive=" << vecInactive.size() << ")";
}
//启用分组,但同组中没有找到,在优先级序列中查找
std::map<int, GroupPriorityEntry> & mapPriority = _mapGroupPriority.getReaderData();
for (std::map<int, GroupPriorityEntry>::iterator it = mapPriority.begin(); it != mapPriority.end() && vecActive.empty(); it++)
{
if (it->second.setGroupID.count(iClientGroupID) == 0)
{
os << "|(Not In Priority " << it->second.sGroupID << ")";
continue;
}
vecActive = getEpsByGroupId(itObject->second.vActiveEndpoints, ENUM_USE_WORK_GROUPID, it->second.setGroupID, os);
vecInactive = getEpsByGroupId(itObject->second.vInactiveEndpoints, ENUM_USE_WORK_GROUPID, it->second.setGroupID, os);
os << "|(In Priority: " << it->second.sGroupID << " Active=" << vecActive.size() << " Inactive=" << vecInactive.size() << ")";
}
//没有同组的endpoit,匹配未启用分组的服务
if (vecActive.empty())
{
vecActive = getEpsByGroupId(itObject->second.vActiveEndpoints, ENUM_USE_WORK_GROUPID, -1, os);
vecInactive = getEpsByGroupId(itObject->second.vInactiveEndpoints, ENUM_USE_WORK_GROUPID, -1, os);
os << "|(In No Grouop: Active=" << vecActive.size() << " Inactive=" << vecInactive.size() << ")";
}
//在未分组的情况下也没有找到,返回全部地址(此时基本上所有的服务都已挂掉)
if (vecActive.empty())
{
vecActive = itObject->second.vActiveEndpoints;
vecInactive = itObject->second.vInactiveEndpoints;
os << "|(In All: Active=" << vecActive.size() << " Inactive=" << vecInactive.size() << ")";
}
return 0;
}
int CDbHandle::findObjectByIdInSameStation(const std::string& sID, const std::string& sStation, std::vector<EndpointF>& vecActive, std::vector<EndpointF>& vecInactive, std::ostringstream& os)
{
vecActive.clear();
vecInactive.clear();
//获得station所有组
std::map<int, GroupPriorityEntry> & mapPriority = _mapGroupPriority.getReaderData();
std::map<int, GroupPriorityEntry>::iterator itGroup = mapPriority.end();
for (itGroup = mapPriority.begin(); itGroup != mapPriority.end(); itGroup++)
{
if (itGroup->second.sStation != sStation) continue;
break;
}
if (itGroup == mapPriority.end())
{
os << "|not found station:" << sStation;
return -1;
}
ObjectsCache& usingCache = _objectsCache.getReaderData();
ObjectsCache::iterator itObject = usingCache.find(sID);
if (itObject == usingCache.end()) return 0;
//查找对应所有组下的IP地址
vecActive = getEpsByGroupId(itObject->second.vActiveEndpoints, ENUM_USE_REAL_GROUPID, itGroup->second.setGroupID, os);
vecInactive = getEpsByGroupId(itObject->second.vInactiveEndpoints, ENUM_USE_REAL_GROUPID, itGroup->second.setGroupID, os);
return 0;
}
int CDbHandle::findObjectByIdInSameSet(const string& sID, const vector<string>& vtSetInfo, std::vector<EndpointF>& vecActive, std::vector<EndpointF>& vecInactive, std::ostringstream& os)
{
string sSetName = vtSetInfo[0];
string sSetArea = vtSetInfo[0] + "." + vtSetInfo[1];
string sSetId = vtSetInfo[0] + "." + vtSetInfo[1] + "." + vtSetInfo[2];
SetDivisionCache& usingSetDivisionCache = _setDivisionCache.getReaderData();
SetDivisionCache::iterator it = usingSetDivisionCache.find(sID);
if (it == usingSetDivisionCache.end())
{
//此情况下没启动set
TLOGINFO("CDbHandle::findObjectByIdInSameSet:" << __LINE__ << "|" << sID << " haven't start set|" << sSetId << endl);
return -1;
}
map<string, vector<SetServerInfo> >::iterator setNameIt = it->second.find(sSetName);
if (setNameIt == (it->second).end())
{
//此情况下没启动set
TLOGINFO("CDbHandle::findObjectByIdInSameSet:" << __LINE__ << "|" << sID << " haven't start set|" << sSetId << endl);
return -1;
}
if (vtSetInfo[2] == "*")
{
//检索通配组和set组中的所有服务
vector<SetServerInfo> vServerInfo = setNameIt->second;
for (size_t i = 0; i < vServerInfo.size(); i++)
{
if (vServerInfo[i].sSetArea == sSetArea)
{
if (vServerInfo[i].bActive)
{
vecActive.push_back(vServerInfo[i].epf);
}
else
{
vecInactive.push_back(vServerInfo[i].epf);
}
}
}
return (vecActive.empty() && vecInactive.empty()) ? -2 : 0;
}
else
{
// 1.从指定set组中查找
int iRet = findObjectByIdInSameSet(sSetId, setNameIt->second, vecActive, vecInactive, os);
if (iRet != 0 && vtSetInfo[2] != "*")
{
// 2. 步骤1中没找到在通配组里找
string sWildSetId = vtSetInfo[0] + "." + vtSetInfo[1] + ".*";
iRet = findObjectByIdInSameSet(sWildSetId, setNameIt->second, vecActive, vecInactive, os);
}
return iRet;
}
}
int CDbHandle::findObjectByIdInSameSet(const string& sSetId, const vector<SetServerInfo>& vSetServerInfo, std::vector<EndpointF>& vecActive, std::vector<EndpointF>& vecInactive, std::ostringstream& os)
{
for (size_t i = 0; i < vSetServerInfo.size(); ++i)
{
if (vSetServerInfo[i].sSetId == sSetId)
{
if (vSetServerInfo[i].bActive)
{
vecActive.push_back(vSetServerInfo[i].epf);
}
else
{
vecInactive.push_back(vSetServerInfo[i].epf);
}
}
}
int iRet = (vecActive.empty() && vecInactive.empty()) ? -2 : 0;
return iRet;
}
void CDbHandle::updateObjectsCache(const ObjectsCache& objCache, bool updateAll)
{
//全量更新
if (updateAll)
{
_objectsCache.getWriterData() = objCache;
_objectsCache.swap();
}
else
{
//用查询数据覆盖一下
_objectsCache.getWriterData() = _objectsCache.getReaderData();
ObjectsCache& tmpObjCache = _objectsCache.getWriterData();
ObjectsCache::const_iterator it = objCache.begin();
for (; it != objCache.end(); it++)
{
//增量的时候加载的是服务的所有节点,因此这里直接替换
tmpObjCache[it->first] = it->second;
}
_objectsCache.swap();
}
}
void CDbHandle::updateInactiveObjectsCache(const ObjectsCache& objCache, bool updateAll)
{
//全量更新
if (updateAll)
{
_objectsCache.getWriterData() = objCache;
_objectsCache.swap();
}
else
{
//用查询数据覆盖一下
_objectsCache.getWriterData() = _objectsCache.getReaderData();
ObjectsCache& tmpObjCache = _objectsCache.getWriterData();
ObjectsCache::const_iterator it = objCache.begin();
for (; it != objCache.end(); it++)
{
//增量的时候加载的是服务的所有节点,因此这里直接替换
tmpObjCache[it->first].vInactiveEndpoints.push_back((it->second).vInactiveEndpoints[0]);
}
_objectsCache.swap();
}
}
void CDbHandle::updateActiveObjectsCache(const ObjectsCache& objCache, bool updateAll)
{
//全量更新
if (updateAll)
{
_objectsCache.getWriterData() = objCache;
_objectsCache.swap();
}
else
{
//用查询数据覆盖一下
_objectsCache.getWriterData() = _objectsCache.getReaderData();
ObjectsCache& tmpObjCache = _objectsCache.getWriterData();
ObjectsCache::const_iterator it = objCache.begin();
for (; it != objCache.end(); it++)
{
//增量的时候加载的是服务的所有节点,因此这里直接替换
tmpObjCache[it->first].vActiveEndpoints.push_back((it->second).vActiveEndpoints[0]);
}
_objectsCache.swap();
}
}
void CDbHandle::addActiveEndPoint(const string& objName, const Int32 port, const Int32 istcp)
{
#define LOCAL_HOST "127.0.0.1"
ObjectsCache objectsCache;
EndpointF endPoint;
endPoint.host = LOCAL_HOST;
endPoint.port = port;
endPoint.timeout = 30000;
endPoint.istcp = istcp;
//endPoint.setId = setName + "." + setArea + "." + setGroup;
objectsCache[objName].vActiveEndpoints.push_back(endPoint);
updateActiveObjectsCache(objectsCache, false);
}
void CDbHandle::addEndPointbySet(const string& objName, const Int32 port, const Int32 istcp, const string& setName, const string& setArea, const string& setGroup)
{
#define LOCAL_HOST "127.0.0.1"
ObjectsCache objectsCache;
EndpointF endPoint;
endPoint.host = LOCAL_HOST;
endPoint.port = port;
endPoint.timeout = 30000;
endPoint.istcp = istcp;
endPoint.setId = setName + "." + setArea + "." + setGroup;
objectsCache[objName].vActiveEndpoints.push_back(endPoint);
updateActiveObjectsCache(objectsCache, false);
if (setName.size())
{
InsertSetRecord(objName, setName, setArea, setGroup, endPoint);
}
}
void CDbHandle::addActiveWeight1EndPoint(const string& objName, const Int32 port, const Int32 istcp, const string& setName)
{
#define LOCAL_HOST "127.0.0.1"
ObjectsCache objectsCache;
EndpointF endPoint;
endPoint.host = LOCAL_HOST;
endPoint.port = port;
endPoint.timeout = 30000;
endPoint.istcp = istcp;
endPoint.setId = setName;
endPoint.weight = 2;
endPoint.weightType = 1;
objectsCache[objName].vActiveEndpoints.push_back(endPoint);
updateActiveObjectsCache(objectsCache, false);
}
void CDbHandle::addInActiveWeight1EndPoint(const string& objName, const Int32 port, const Int32 istcp, const string& setName)
{
#define LOCAL_HOST "127.0.0.1"
ObjectsCache objectsCache;
EndpointF endPoint;
endPoint.host = LOCAL_HOST;
endPoint.port = port;
endPoint.timeout = 30000;
endPoint.istcp = istcp;
endPoint.setId = setName;
endPoint.weight = 2;
endPoint.weightType = 1;
objectsCache[objName].vInactiveEndpoints.push_back(endPoint);
updateInactiveObjectsCache(objectsCache, false);
}
void CDbHandle::addActiveWeight2EndPoint(const string& objName, const Int32 port, const Int32 istcp, const string& setName)
{
#define LOCAL_HOST "127.0.0.1"
ObjectsCache objectsCache;
EndpointF endPoint;
endPoint.host = LOCAL_HOST;
endPoint.port = port;
endPoint.timeout = 30000;
endPoint.istcp = istcp;
endPoint.setId = setName;
endPoint.weight = 2;
endPoint.weightType = 2;
objectsCache[objName].vActiveEndpoints.push_back(endPoint);
updateActiveObjectsCache(objectsCache, false);
}
void CDbHandle::addInactiveEndPoint(const string& objName, const Int32 port, const Int32 istcp)
{
#define LOCAL_HOST "127.0.0.1"
ObjectsCache objectsCache;
EndpointF endPoint;
endPoint.host = LOCAL_HOST;
endPoint.port = port;
endPoint.timeout = 30000;
endPoint.istcp = istcp;
//endPoint.setId = setName;
objectsCache[objName].vInactiveEndpoints.push_back(endPoint);
updateInactiveObjectsCache(objectsCache, false);
}
void CDbHandle::cleanEndPoint()
{
ObjectsCache objectsCache;
updateObjectsCache(objectsCache, true);
}
int CDbHandle::getGroupId(const string& ip)
{
map<string, int>& groupIdMap = _groupIdMap.getReaderData();
map<string, int>::iterator it = groupIdMap.find(ip);
if (it != groupIdMap.end())
{
return it->second;
}
uint32_t uip = stringIpToInt(ip);
string ipStar = Ip2StarStr(uip);
it = groupIdMap.find(ipStar);
if (it != groupIdMap.end())
{
return it->second;
}
return -1;
}
uint32_t CDbHandle::stringIpToInt(const std::string& sip)
{
string ip1, ip2, ip3, ip4;
uint32_t dip, p1, p2, p3;
dip = 0;
p1 = sip.find('.');
p2 = sip.find('.', p1 + 1);
p3 = sip.find('.', p2 + 1);
ip1 = sip.substr(0, p1);
ip2 = sip.substr(p1 + 1, p2 - p1 - 1);
ip3 = sip.substr(p2 + 1, p3 - p2 - 1);
ip4 = sip.substr(p3 + 1, sip.size() - p3 - 1);
(((unsigned char *)&dip)[0]) = TC_Common::strto<unsigned int>(ip1);
(((unsigned char *)&dip)[1]) = TC_Common::strto<unsigned int>(ip2);
(((unsigned char *)&dip)[2]) = TC_Common::strto<unsigned int>(ip3);
(((unsigned char *)&dip)[3]) = TC_Common::strto<unsigned int>(ip4);
return htonl(dip);
}
string CDbHandle::Ip2Str(uint32_t ip)
{
char str[50];
unsigned char *p = (unsigned char *)&ip;
sprintf(str, "%u.%u.%u.%u", p[3], p[2], p[1], p[0]);
return string(str);
}
string CDbHandle::Ip2StarStr(uint32_t ip)
{
char str[50];
unsigned char *p = (unsigned char *)&ip;
sprintf(str, "%u.%u.%u.*", p[3], p[2], p[1]);
return string(str);
}
void CDbHandle::InsertSetRecord(const string& objName, const string& setName, const string& setArea, const string& setGroup, EndpointF epf)
{
SetDivisionCache setDivisionCache;
string setId = setName + "." + setArea + "." + setGroup;
SetServerInfo setServerInfo;
setServerInfo.bActive = true;
setServerInfo.epf = epf;
setServerInfo.sSetId = setId;
setServerInfo.sSetArea = setArea;
setDivisionCache[objName][setName].push_back(setServerInfo);
setServerInfo.bActive = false;
setServerInfo.epf.port = 10204;
setDivisionCache[objName][setName].push_back(setServerInfo);
updateDivisionCache(setDivisionCache, true);
}
void CDbHandle::InsertSetRecord4Inactive(const string& objName, const string& setName, const string& setArea, const string& setGroup, EndpointF epf)
{
SetDivisionCache setDivisionCache;
string setId = setName + "." + setArea + "." + setGroup;
SetServerInfo setServerInfo;
setServerInfo.bActive = false;
setServerInfo.epf = epf;
setServerInfo.sSetId = setId;
setServerInfo.sSetArea = setArea;
setDivisionCache[objName][setName].push_back(setServerInfo);
updateDivisionCache(setDivisionCache, false);
}
void CDbHandle::updateDivisionCache(SetDivisionCache& setDivisionCache,bool updateAll)
{
//ȫ<><C8AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if(updateAll)
{
if (setDivisionCache.size() == 0)
{
return;
}
SetDivisionCache::iterator it = setDivisionCache.begin();
for(;it != setDivisionCache.end();it++)
{
if(it->second.size() > 0)
{
map<string,vector<CDbHandle::SetServerInfo> >::iterator it_inner = it->second.begin();
for(;it_inner != it->second.end();it_inner++)
{
//updateCpuLoadInfo(it_inner->second);
}
}
}
_setDivisionCache.getWriterData() = setDivisionCache;
_setDivisionCache.swap();
}
else
{
_setDivisionCache.getWriterData() = _setDivisionCache.getReaderData();
SetDivisionCache& tmpsetCache = _setDivisionCache.getWriterData();
SetDivisionCache::const_iterator it = setDivisionCache.begin();
for(;it != setDivisionCache.end();it++)
{
//<2F><>set<65><74>Ϣ<EFBFBD>Ÿ<EFBFBD><C5B8><EFBFBD>
if(it->second.size() > 0)
{
tmpsetCache[it->first] = it->second;
}
else if(tmpsetCache.count(it->first))
{
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>нڵ㶼û<E3B6BC><C3BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>set<65><74>ɾ<EFBFBD><C9BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>е<EFBFBD>set<65><74>Ϣ
tmpsetCache.erase(it->first);
}
}
_setDivisionCache.swap();
}
}
#if 0
void CDbHandle::updateCpuLoadInfo(vector<EndpointF> &vEndpointF)
{
CpuLoadCache &cpuLoadCacheMap = _cpuLoadCacheMap.getReaderData();
for(size_t i = 0; i < vEndpointF.size(); ++i)
{
map<string,CpuLoadInfo>::const_iterator const_it_cpu = cpuLoadCacheMap.find(vEndpointF[i].host);
if(const_it_cpu != cpuLoadCacheMap.end())
{
struct tm tb;
int ret = TC_Common::str2tm(const_it_cpu->second.sHeartTime, "%Y-%m-%d %H:%M:%S", tb);
if(ret == 0)
{
vEndpointF[i].cpuload = const_it_cpu->second.iCpuLoad;
vEndpointF[i].sampletime = mktime(&tb);
}
else
{
vEndpointF[i].cpuload = -1;
vEndpointF[i].sampletime = 0;
}
}
else
{
vEndpointF[i].cpuload = -1;
vEndpointF[i].sampletime = 0;
}
}
}
void CDbHandle::updateCpuLoadInfo(vector<CDbHandle::SetServerInfo> &vSetServerInfo)
{
CpuLoadCache &cpuLoadCacheMap = _cpuLoadCacheMap.getReaderData();
for(size_t i = 0; i < vSetServerInfo.size(); ++i)
{
map<string,CpuLoadInfo>::const_iterator const_it_cpu = cpuLoadCacheMap.find(vSetServerInfo[i].epf.host);
if(const_it_cpu != cpuLoadCacheMap.end())
{
struct tm tb;
int ret = TC_Common::str2tm(const_it_cpu->second.sHeartTime, "%Y-%m-%d %H:%M:%S", tb);
if(ret == 0)
{
vSetServerInfo[i].epf.cpuload = const_it_cpu->second.iCpuLoad;
vSetServerInfo[i].epf.sampletime = mktime(&tb);
}
else
{
vSetServerInfo[i].epf.cpuload = -1;
vSetServerInfo[i].epf.sampletime = 0;
}
}
else
{
vSetServerInfo[i].epf.cpuload = -1;
vSetServerInfo[i].epf.sampletime = 0;
}
}
}
#endif

View File

@ -0,0 +1,214 @@
#ifndef __DB_HANDLE_H__
#define __DB_HANDLE_H__
#include "util/tc_common.h"
#include "util/tc_config.h"
#include "util/tc_monitor.h"
#include "util/tc_file.h"
#include "jmem/jmem_hashmap.h"
#include "util/tc_readers_writer_data.h"
#include <set>
#include "servant/RemoteLogger.h"
#include "servant/EndpointF.h"
#include "RegistryDescriptor.h"
using namespace tars;
//////////////////////////////////////////////////////
//<servant, ObjectItem>
typedef map<string, ObjectItem> ObjectsCache;
//////////////////////////////////////////////////////
/**
*
*/
class CDbHandle
{
private:
struct GroupPriorityEntry
{
std::string sGroupID;
std::string sStation;
std::set<int> setGroupID;
};
enum GroupUseSelect
{
ENUM_USE_WORK_GROUPID,
ENUM_USE_REAL_GROUPID
};
//set中服务的信息
struct SetServerInfo
{
string sSetId;
string sSetArea;
bool bActive;
EndpointF epf;
};
//<servant,setname,vector>
typedef map<string,map<string,vector<CDbHandle::SetServerInfo> > > SetDivisionCache;
public:
/**
*
*/
CDbHandle()
{
}
/**
*
* @param pconf
* @return 0- others-
*/
int init(TC_Config *pconf);
/** 根据id获取对象
*
* @param id
*
* @return endpoint列表
*/
vector<EndpointF> findObjectById(const string & id);
/** 根据id获取对象
*
* @param id
* @out param activeEp
* @out param inactiveEp
*
* @return 0- others-
*/
int findObjectById4All(const string & id, vector<EndpointF>& activeEp, vector<EndpointF>& inactiveEp);
/** 根据id获取同组对象
*
* @param id
* @param ip
* @out param activeEp
* @out param inactiveEp
* @out param os 使
*
* @return 0- others-
*/
int findObjectByIdInSameGroup(const string & id, const string & ip, vector<EndpointF>& activeEp, vector<EndpointF>& inactiveEp, ostringstream &os);
/** 根据id获取优先级序列中的对象
*
* @param id
* @param ip
* @out param vecActive
* @out param vecInactive
* @out param os 使
*
* @return 0- others-
*/
int findObjectByIdInGroupPriority(const std::string &sID, const std::string &sIP, std::vector<EndpointF> & vecActive, std::vector<EndpointF> & vecInactive, std::ostringstream & os);
/** 根据id和归属地获取全部对象
*
* @param id
* @param sStation
* @out param vecActive
* @out param vecInactive
* @out param os 使
*
* @return 0- others-
*/
int findObjectByIdInSameStation(const std::string &sID, const std::string & sStation, std::vector<EndpointF> & vecActive, std::vector<EndpointF> & vecInactive, std::ostringstream & os);
/** 根据id和set信息获取全部对象
*
* @param sID
* @param vtSetInfo set信息
* @out param vecActive
* @out param vecInactive
* @out param os 使
*
* @return 0- others-
*/
int findObjectByIdInSameSet(const string &sID, const vector<string> &vtSetInfo, std::vector<EndpointF> & vecActive, std::vector<EndpointF> & vecInactive, std::ostringstream & os);
/** 根据setId获取全部对象
*
* @param sSetId set名称
* @param vSetServerInfo SetName下部署的服务信息
* @out param vecActive
* @out param vecInactive
* @out param os 使
*
* @return 0- others-
*/
int findObjectByIdInSameSet(const string &sSetId, const vector<SetServerInfo>& vSetServerInfo, std::vector<EndpointF> & vecActive, std::vector<EndpointF> & vecInactive, std::ostringstream & os);
/**
* ip获取组id
* @return int <0
*/
int getGroupId(const string& ip);
/**
* ip转换
*/
static uint32_t stringIpToInt(const std::string& sip);
/**
* ip转换
*/
static string Ip2Str(uint32_t ip);
/**
* ip转换
*/
static string Ip2StarStr(uint32_t ip);
static void updateObjectsCache(const ObjectsCache& objCache, bool updateAll);
static void updateActiveObjectsCache(const ObjectsCache& objCache, bool updateAll);
static void updateInactiveObjectsCache(const ObjectsCache& objCache, bool updateAll);
static void updateDivisionCache(SetDivisionCache& setDivisionCache,bool updateAll);
static void updateCpuLoadInfo(vector<EndpointF> &vEndpointF);
static void updateCpuLoadInfo(vector<CDbHandle::SetServerInfo> &vSetServerInfo);
static void InsertSetRecord(const string& objName, const string& setName, const string& setArea, const string& setGroup, EndpointF epf);
static void InsertSetRecord4Inactive(const string& objName, const string& setName, const string& setArea, const string& setGroup, EndpointF epf);
static void addActiveEndPoint(const string& objName, const Int32 port, const Int32 istcp);
static void addInactiveEndPoint(const string& objName, const Int32 port, const Int32 istcp);
static void addEndPointbySet(const string& objName, const Int32 port, const Int32 istcp, const string& setName, const string& setArea, const string& setGroup);
static void addActiveWeight1EndPoint(const string& objName, const Int32 port, const Int32 istcp, const string& setName = "");
static void addInActiveWeight1EndPoint(const string& objName, const Int32 port, const Int32 istcp, const string& setName = "");
static void addActiveWeight2EndPoint(const string& objName, const Int32 port, const Int32 istcp, const string& setName = "");
static void cleanEndPoint();;
protected:
/**
* group id获取Endpoint
*/
vector<EndpointF> getEpsByGroupId(const vector<EndpointF> & vecEps, const GroupUseSelect GroupSelect, int iGroupId, ostringstream &os);
vector<EndpointF> getEpsByGroupId(const vector<EndpointF> & vecEps, const GroupUseSelect GroupSelect, const set<int> & setGroupID, ostringstream & os);
protected:
static TC_ReadersWriterData<ObjectsCache> _objectsCache;
//set划分缓存
static TC_ReadersWriterData<SetDivisionCache> _setDivisionCache;
//优先级的序列
static TC_ReadersWriterData<std::map<int, GroupPriorityEntry> > _mapGroupPriority;
//分组信息
static TC_ReadersWriterData<map<string,int> > _groupIdMap;
static TC_ReadersWriterData<map<string,int> > _groupNameMap;
};
#endif

View File

@ -0,0 +1,437 @@
/**
* Tencent is pleased to support the open source community by making Tars available.
*
* Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
#include "LogImp.h"
#include "servant/RemoteLogger.h"
GlobeInfo g_globe;
TC_DayLogger& GlobeInfo::makeDayLogger(const string &app, const string &server, const string &logname, const string &format,const string& ip)
{
string sLogPath = _log_path + "/" + app + "/" + server + "/" + logname;
TLOGDEBUG("GlobeInfo::makeDayLogger sLogPath:" << sLogPath << "|format:" << format << endl);
DLOG << "GlobeInfo::makeDayLogger sLogPath:" << sLogPath << "|format:" << format << endl;
TC_DayLogger *p = new TC_DayLogger();
p->init(sLogPath, format);
p->setupThread(&_group);
//所有标识都不要
p->modFlag(0xffff, false);
_loggers[logname][ip] = p;
_formats[logname][ip] = format;
return (*p);
}
TC_DayLogger& GlobeInfo::makeDayLogger(const LogInfo & info, const string &logname, const string &format,const string& ip)
{
string sLogPath = getRealLogName(info);
//获取配置中的记录方式
string sFormat = format;
string sLogType = info.sLogType;
string sKey = info.appname + "." +info.servername + "." + info.sFilename;
map<string,string>::iterator it = _mLogType.find(sKey);
if(it != _mLogType.end())
{
//服务端的配置优先级最高
sLogType = it->second;
//使用规范格式
sFormat = "";
}
TLOGDEBUG("GlobeInfo::makeDayLogger sLogPath:" << sLogPath << "|app:" << info.appname << "|server:" << info.servername << "|filename:" << info.sFilename
<< "|format:" << format << "|setdivision:" << info.setdivision << "|bHasSufix:" << info.bHasSufix << "|bHasAppNamePrefix:" << info.bHasAppNamePrefix
<< "|sConcatStr" << info.sConcatStr << "|sSepar" << info.sSepar << "|sLogType:" << sLogType << endl);
DLOG << "GlobeInfo::makeDayLogger sLogPath:" << sLogPath << "|app:" << info.appname << "|server:" << info.servername << "|filename:" << info.sFilename
<< "|format:" << format << "|setdivision:" << info.setdivision << "|bHasSufix:" << info.bHasSufix << "|bHasAppNamePrefix:" << info.bHasAppNamePrefix
<< "|sConcatStr" << info.sConcatStr << "|sSepar" << info.sSepar << "|sLogType:" << sLogType <<endl;
TC_DayLogger *p = new TC_DayLogger();
p->init(sLogPath, format,info.bHasSufix,info.sConcatStr,getTarsLogType(sFormat,sLogType));
p->setSeparator(info.sSepar);
p->enableSqareWrapper(info.bHasSquareBracket);
p->setupThread(&_group);
//所有标识都不要
p->modFlag(0xffff, false);
_loggers[logname][ip] = p;
_formats[logname][ip] = format;
return (*p);
}
LogTypePtr GlobeInfo::getTarsLogType(const string& sFormat,const string& sCutType)
{
LogTypePtr logTypePtr = NULL;
if(sCutType != "")
{
string sType = TC_Common::lower(sCutType);
string::size_type pos = string::npos;
if((pos = sType.find("day")) != string::npos)
{
int n = 1;
if(sType.substr(0,pos) != "" && TC_Common::isdigit(sType.substr(0,pos)) == true)
{
n = TC_Common::strto<int>(sType.substr(0,pos));
}
string format = (sFormat=="") ? LogByDay::FORMAT : sFormat;
logTypePtr = new LogByDay(format,n);
}
else if((pos = sType.find("hour")) != string::npos)
{
int n = 1;
if(sType.substr(0,pos) != "" && TC_Common::isdigit(sType.substr(0,pos)) == true)
{
n = TC_Common::strto<int>(sType.substr(0,pos));
}
string format = (sFormat=="") ? LogByHour::FORMAT : sFormat;
logTypePtr = new LogByHour(format,n);
}
else if((pos = sType.find("minute")) != string::npos)
{
int n = 10;//支持5,10分钟
if(sType.substr(0,pos) != "" && TC_Common::isdigit(sType.substr(0,pos)) == true)
{
n = TC_Common::strto<int>(sType.substr(0,pos));
}
string format = (sFormat=="") ? LogByMinute::FORMAT : sFormat;
logTypePtr = new LogByMinute(format,n);
}
}
return logTypePtr;
}
string GlobeInfo::getRealLogName(const LogInfo & info)
{
string sRealLogname;
if(info.bHasAppNamePrefix)
{
sRealLogname = info.sFilename.empty() ? (info.appname +"." + info.servername) : \
(info.appname +"." + info.servername + info.sConcatStr + info.sFilename);
}
else
{
sRealLogname = info.sFilename;
}
string setDivision = getSetGoodFormat(info.setdivision);
string sLogPath = _log_path + "/" + info.appname + "/" + setDivision + "/" + info.servername + "/" + sRealLogname;
return sLogPath;
}
string GlobeInfo::getLogName(const LogInfo & info)
{
string sLogname = TC_Common::tostr<bool>(info.bHasSufix) + info.sConcatStr + TC_Common::tostr<bool>(info.bHasAppNamePrefix) + info.sConcatStr +\
TC_Common::tostr<bool>(info.bHasSquareBracket) + info.sConcatStr + info.sSepar + info.sConcatStr +\
info.setdivision + info.sConcatStr + info.appname + info.sConcatStr + info.servername + info.sConcatStr + info.sFilename + info.sConcatStr + info.sLogType;
return sLogname;
}
bool GlobeInfo::HasSameFormat(const string& logname,const string& format,string& ip)
{
map<string,string>::iterator itFormat = _formats[logname].begin();
bool bHasFormat = false; //是否有创建过的format
for(; itFormat != _formats[logname].end(); itFormat++)
{
if(itFormat->second == format) //找到创建过的format
{
bHasFormat = true;
ip = itFormat->first; //为创建过相同format的节点ip
break;
}
}
return bHasFormat;
}
bool GlobeInfo::IsLoggerAttached(const string& logname,const string& sExcludeIp,const TC_DayLogger* pLogger)
{
map<string,TC_DayLogger*>::iterator itLogger = _loggers[logname].begin();
bool bIsAttached = false; //是否有ip在用该logger实例
for(; itLogger != _loggers[logname].end(); itLogger++)
{
if(itLogger->first != sExcludeIp && itLogger->second == pLogger)
{
bIsAttached = true;
TLOGDEBUG("GlobeInfo::IsLoggerAttached first:" << itLogger->first<< endl);
break;
}
}
return bIsAttached;
}
TC_DayLogger& GlobeInfo::getLogger(const LogInfo & info,const string& ip)
{
string format = info.sFormat;
if(binary_search(_vHourlist.begin(), _vHourlist.end(), (info.appname + "." + info.servername)) != false)
{
format = "%Y%m%d%H";
}
string setDivision = getSetGoodFormat(info.setdivision);
if(!TC_File::isFileExistEx((_log_path + "/" + info.appname + "/" + setDivision + "/" + info.servername), S_IFDIR))
{
TC_File::makeDirRecursive(_log_path + "/" + info.appname + "/" + setDivision + "/" + info.servername);
}
string logname = getLogName(info);
TLOGDEBUG("GlobeInfo::getLogger logname:" << logname << "|format:" << format << "|setDivision:" << setDivision << endl);
Lock lock(*this);
map<string, map<string,TC_DayLogger*> >::iterator itLogName = _loggers.find(logname);
if( itLogName == _loggers.end()) //没有创建过的log
{
return makeDayLogger(info, logname, format, ip);
}
map<string,TC_DayLogger*>::iterator itIp = itLogName->second.find(ip);
if(itIp == itLogName->second.end()) //没有创建过的ip节点
{
string sSameIp("");
if(HasSameFormat(logname,format,sSameIp)) //有创建过的format,把新的节点ip划分到同组
{
_loggers[logname][ip] = _loggers[logname][sSameIp];//使用具有相同format的logger实例
_formats[logname][ip] = format;
return (*(_loggers[logname][ip]));
}
else //没有创建过该format,新建立一个logname下的format组
{
return makeDayLogger(info, logname, format,ip);
}
}
else //该logname下的这个ip节点创建过
{
if(_formats[logname][ip] != format) //该ip节点的日志格式变化了
{
string sSameIp("");
TC_DayLogger* pOldLogger = _loggers[logname][ip];
if(HasSameFormat(logname,format,sSameIp))//已经有该格式,归入同组
{
_loggers[logname][ip] = _loggers[logname][sSameIp];
_formats[logname][ip] = format;
if(pOldLogger) //删除旧的loger
{
pOldLogger->unSetupThread();
delete pOldLogger;
pOldLogger = NULL;
}
return (*(_loggers[logname][ip]));
}
else
{
_loggers[logname][ip] = NULL;
_formats[logname][ip] = "";
if(!IsLoggerAttached(logname,ip,pOldLogger))//可能有多个节点引用这个loger这里需要判断
{
pOldLogger->unSetupThread();
delete pOldLogger;
pOldLogger = NULL;
}
return makeDayLogger(info, logname, format,ip);
}
}
}
//没有改变格式
return (*(_loggers[logname][ip]));
}
TC_DayLogger& GlobeInfo::getLogger(const string &app, const string &server, const string &file, const string &sformat,const string& ip)
{
if(!TC_File::isFileExistEx((_log_path + "/" + app + "/" + server), S_IFDIR))
{
TC_File::makeDirRecursive(_log_path + "/" + app + "/" + server);
}
string format = sformat;
if(binary_search(_vHourlist.begin(),_vHourlist.end(),(app + "." + server)) != false)
{
format = "%Y%m%d%H";
}
string logname = file.empty() ? (app + "." + server) : (app + "." + server + "_" + file);
TLOGDEBUG("GlobeInfo::getLogger logname:" << logname << "|format:" << format << endl);
Lock lock(*this);
map<string, map<string,TC_DayLogger*> >::iterator itLogName = _loggers.find(logname);
if( itLogName == _loggers.end()) //没有创建过的log
{
return makeDayLogger(app, server, logname, format,ip);
}
map<string,TC_DayLogger*>::iterator itIp = itLogName->second.find(ip);
if(itIp == itLogName->second.end()) //没有创建过的ip节点
{
string sSameIp("");
if(HasSameFormat(logname,format,sSameIp)) //有创建过的format,把新的节点ip划分到同组
{
_loggers[logname][ip] = _loggers[logname][sSameIp];//使用具有相同format的logger实例
_formats[logname][ip] = format;
return (*(_loggers[logname][ip]));
}
else //没有创建过该format,新建立一个logname下的format组
{
return makeDayLogger(app, server, logname, format,ip);
}
}
else //该logname下的这个ip节点创建过
{
if(_formats[logname][ip] != format) //该ip节点的日志格式变化了
{
string sSameIp("");
TC_DayLogger* pOldLogger = _loggers[logname][ip];
if(HasSameFormat(logname,format,sSameIp))//已经有该格式,归入同组
{
_loggers[logname][ip] = _loggers[logname][sSameIp];
_formats[logname][ip] = format;
if(pOldLogger) //删除旧的loger
{
pOldLogger->unSetupThread();
delete pOldLogger;
pOldLogger = NULL;
}
return (*(_loggers[logname][ip]));
}
else
{
_loggers[logname][ip] = NULL;
_formats[logname][ip] = "";
if(!IsLoggerAttached(logname,ip,pOldLogger))//可能有多个节点引用这个loger这里需要判断
{
pOldLogger->unSetupThread();
delete pOldLogger;
pOldLogger = NULL;
}
return makeDayLogger(app, server, logname, format,ip);
}
}
}
//没有改变格式
return (*(_loggers[logname][ip]));
}
string GlobeInfo::getSetGoodFormat(const string& sSetDivision)
{
vector<string> vtSetDivisions = TC_Common::sepstr<string>(sSetDivision,".");
if(vtSetDivisions.size() != 3)
{
return "";
}
else
{
if(vtSetDivisions[2] == "*")
{
return string(vtSetDivisions[0] + vtSetDivisions[1]);
}
else
{
return string(vtSetDivisions[0] + vtSetDivisions[1] + vtSetDivisions[2]);
}
}
}
void GlobeInfo::update(const vector<string> &vHourlist, const map<string,string> &mLogType)
{
Lock lock(*this);
_vHourlist = vHourlist;
_mLogType = mLogType;
}
//////////////////////////////////////////
//
void LogImp::initialize()
{
}
void LogImp::logger(const string &app, const string &server, const string &file, const string &format, const vector<string> &buffer, tars::TarsCurrentPtr current)
{
LOG_CONSOLE_DEBUG << app << ", " << server << ", " << file << ", " << format << endl;
TC_DayLogger &dl = g_globe.getLogger(app, server, file, format,current->getIp());
//记录日志
for(size_t i = 0; i < buffer.size(); i++)
{
if(g_globe._bIpPrefix)
{
dl.any() << current->getIp() << "|" << buffer[i];
}
else
{
dl.any() << buffer[i];
}
}
}
void LogImp::loggerbyInfo(const LogInfo & info,const vector<std::string> & buffer,tars::TarsCurrentPtr current)
{
LOG_CONSOLE_DEBUG << info.writeToJsonString() << endl;
TC_DayLogger &dl = g_globe.getLogger(info,current->getIp());
//记录日志
for(size_t i = 0; i < buffer.size(); i++)
{
if(g_globe._bIpPrefix)
{
dl.any() << current->getIp() << info.sSepar << buffer[i];
}
else
{
dl.any() << buffer[i];
}
}
}

View File

@ -0,0 +1,222 @@
/**
* Tencent is pleased to support the open source community by making Tars available.
*
* Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
*
* Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* https://opensource.org/licenses/BSD-3-Clause
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
#ifndef __LOG_IMP_H_
#define __LOG_IMP_H_
#include "servant/LogF.h"
#include "util/tc_common.h"
#include "util/tc_file.h"
#include "util/tc_logger.h"
#include "util/tc_monitor.h"
//#include "LogServer.h"
using namespace tars;
/**
*
*/
struct GlobeInfo : public TC_ThreadLock
{
public:
/**
*
* @param app
* @param server
* @param file
* @param format
* @param ip ip
*
* @return TC_DayLogger&
*/
TC_DayLogger& getLogger(const string &app, const string &server, const string &file, const string &format,const string& ip);
/**
*
* @param info LogInfo
* @param ip ip
*
* @return TC_DayLogger&
*/
TC_DayLogger& getLogger(const LogInfo & info,const string& ip);
/**
* _vHourlist和_mLogType配置
*/
void update(const vector<string> &vHourlist, const map<string,string> &mLogType);
protected:
/**
*
* @param info LogInfo
* @param logname
* @param format
* @param ip ip
*
* @return TC_DayLogger&
*/
TC_DayLogger& makeDayLogger(const LogInfo & info, const string &logname, const string &format,const string& ip);
/**
*
* @param app
* @param server
* @param logname
* @param format
* @param ip ip
*
* @return TC_DayLogger&
*/
TC_DayLogger& makeDayLogger(const string &app, const string &server, const string &logname, const string &format,const string& ip);
/**
* logname下是否有指定的format
* @param logname file.empty() ? (app + "." + server) : (app + "." + server + "_" + file)
* @param format
* @param[out] ip format存在format对应的节点ip
*
* @return bool
*/
bool HasSameFormat(const string& logname,const string& format,string& ip);
/**
* logname下sExcludeIp外使pLoger指定的logger实例
* @param logname
* @param sExcludeIp
* @param pLogger
*
* @return bool
*/
bool IsLoggerAttached(const string& logname,const string& sExcludeIp,const TC_DayLogger* pLoger);
private:
/**
* set完整格式
* @param sSetDivision set分组信息,:mtt.s.1 mtt.s.*
*
* @return :mtt.s.* "*"mttsmtts1则原样返回
*/
string getSetGoodFormat(const string& sSetDivision);
/**
* LogInfo中获取相关信息得到标识一个logger对象的字符串
* @param info
*/
string getLogName(const LogInfo & info);
/**
* LogInfo中获取日志文件名称
* @param info
*/
string getRealLogName(const LogInfo & info);
LogTypePtr getTarsLogType(const string& sFormat, const string& sCutType);
public:
/**
* 线
*/
TC_LoggerThreadGroup _group;
/**
*
*/
string _log_path;
/**
* logger对象:logname,ip,logger
*/
map<string, map<string,TC_DayLogger*> > _loggers;
/**
* logger格式:logname,ip,format
*/
map<string, map<string,string> > _formats;
/**
*
*/
vector<string> _vHourlist;
/**
*
* key:: appname.servername.filename
* value::hour,2hour,5minute,10minute
*/
map<string,string> _mLogType;
/**
*ip
*/
bool _bIpPrefix;
};
extern GlobeInfo g_globe;
/**
* log实现
*/
class LogImp : public Log
{
public:
/**
*
*/
LogImp(){};
/**
*
*/
~LogImp(){};
/**
*
*
* @return int
*/
virtual void initialize();
/**
* 退
*/
virtual void destroy() {};
/**
*
* @param app
* @param server
* @param file
* @param format
* @param buffer
*
*
*/
void logger(const string &app, const string &server, const string &file, const string &format, const vector<string> &buffer, tars::TarsCurrentPtr current);
/**
*
* @param info
* @param buffer
*
*/
void loggerbyInfo(const LogInfo & info,const vector<std::string> & buffer,tars::TarsCurrentPtr current);
private:
};
#endif

View File

@ -0,0 +1,196 @@
#include "QueryImp.h"
#include "util/tc_logger.h"
#include "util/tc_clientsocket.h"
void QueryImp::initialize()
{
TLOGDEBUG("begin QueryImp init"<<endl);
}
vector<EndpointF> QueryImp::findObjectById(const string & id, tars::CurrentPtr current)
{
LOG_CONSOLE_DEBUG << endl;
vector<EndpointF> eps = _db.findObjectById(id);
ostringstream os;
doDaylog(FUNID_findObjectById,id,eps,vector<EndpointF>(),current,os);
return eps;
}
tars::Int32 QueryImp::findObjectById4Any(const std::string & id,vector<tars::EndpointF> &activeEp,vector<tars::EndpointF> &inactiveEp,tars::CurrentPtr current)
{
LOG_CONSOLE_DEBUG << endl;
int iRet = _db.findObjectById4All(id, activeEp, inactiveEp);
ostringstream os;
doDaylog(FUNID_findObjectById4Any,id,activeEp,inactiveEp,current,os);
return iRet;
}
int QueryImp::findObjectById4All(const std::string & id, vector<tars::EndpointF> &activeEp,vector<tars::EndpointF> &inactiveEp,tars::CurrentPtr current)
{
LOG_CONSOLE_DEBUG << endl;
ostringstream os;
int iRet = _db.findObjectByIdInGroupPriority(id,current->getIp(),activeEp, inactiveEp,os);
doDaylog(FUNID_findObjectById4All,id,activeEp,inactiveEp,current,os);
return iRet;
}
int QueryImp::findObjectByIdInSameGroup(const std::string & id, vector<tars::EndpointF> &activeEp,vector<tars::EndpointF> &inactiveEp, tars::CurrentPtr current)
{
LOG_CONSOLE_DEBUG << endl;
ostringstream os;
TLOGINFO(__FUNCTION__ << ":" << __LINE__ << "|" << id << "|" << current->getIp() << endl);
int iRet = _db.findObjectByIdInGroupPriority(id, current->getIp(), activeEp, inactiveEp, os);
doDaylog(FUNID_findObjectByIdInSameGroup,id,activeEp,inactiveEp,current,os);
return iRet;
}
Int32 QueryImp::findObjectByIdInSameStation(const std::string & id, const std::string & sStation, vector<tars::EndpointF> &activeEp, vector<tars::EndpointF> &inactiveEp, tars::CurrentPtr current)
{
LOG_CONSOLE_DEBUG << endl;
ostringstream os;
int iRet = _db.findObjectByIdInSameStation(id, sStation, activeEp, inactiveEp, os);
doDaylog(FUNID_findObjectByIdInSameStation,id,activeEp,inactiveEp,current,os);
return iRet;
}
Int32 QueryImp::findObjectByIdInSameSet(const std::string & id,const std::string & setId,vector<tars::EndpointF> &activeEp,vector<tars::EndpointF> &inactiveEp, tars::CurrentPtr current)
{
LOG_CONSOLE_DEBUG << endl;
vector<string> vtSetInfo = TC_Common::sepstr<string>(setId,".");
if (vtSetInfo.size()!=3 ||(vtSetInfo.size()==3&&(vtSetInfo[0]=="*"||vtSetInfo[1]=="*")))
{
TLOGERROR("QueryImp::findObjectByIdInSameSet:|set full name error[" << id << "_" << setId <<"]|" << current->getIp() << endl);
return -1;
}
ostringstream os;
int iRet = _db.findObjectByIdInSameSet(id, vtSetInfo, activeEp, inactiveEp, os);
if (-1 == iRet)
{
//未启动set启动ip分组策略
return findObjectByIdInSameGroup(id, activeEp, inactiveEp, current);
}
else if (-2 == iRet)
{
//启动了set但未找到任何服务节点
TLOGERROR("QueryImp::findObjectByIdInSameSet |no one server found for [" << id << "_" << setId <<"]|" << current->getIp() << endl);
return -1;
}
else if (-3 == iRet)
{
//启动了set但未找到任何地区set,严格上不应该出现此类情形,配置错误或主调设置错误会引起此类错误
TLOGERROR("QueryImp::findObjectByIdInSameSet |no set area found [" << id << "_" << setId <<"]|" << current->getIp() << endl);
return -1;
}
doDaylog(FUNID_findObjectByIdInSameSet,id,activeEp,inactiveEp,current,os,setId);
return iRet;
}
void QueryImp::doDaylog(const FUNID eFnId,const string& id,const vector<tars::EndpointF> &activeEp, const vector<tars::EndpointF> &inactiveEp, const tars::CurrentPtr& current,const ostringstream& os,const string& sSetid)
{
string sEpList;
for(size_t i = 0; i < activeEp.size(); i++)
{
if(0 != i)
{
sEpList += ";";
}
sEpList += activeEp[i].host + ":" + TC_Common::tostr(activeEp[i].port);
}
sEpList += "|";
for(size_t i = 0; i < inactiveEp.size(); i++)
{
if(0 != i)
{
sEpList += ";";
}
sEpList += inactiveEp[i].host + ":" + TC_Common::tostr(inactiveEp[i].port);
}
switch(eFnId)
{
case FUNID_findObjectById4All:
case FUNID_findObjectByIdInSameGroup:
{
FDLOG("query_idc") << eFunTostr(eFnId)<<"|"<<current->getIp() << "|"<< current->getPort() << "|" << id << "|" <<sSetid << "|" << sEpList <<os.str()<< endl;
}
break;
case FUNID_findObjectByIdInSameSet:
{
FDLOG("query_set") << eFunTostr(eFnId)<<"|"<<current->getIp() << "|"<< current->getPort() << "|" << id << "|" <<sSetid << "|" << sEpList <<os.str()<< endl;
}
break;
case FUNID_findObjectById4Any:
case FUNID_findObjectById:
case FUNID_findObjectByIdInSameStation:
default:
{
FDLOG("query") << eFunTostr(eFnId)<<"|"<<current->getIp() << "|"<< current->getPort() << "|" << id << "|" <<sSetid << "|" << sEpList <<os.str()<< endl;
}
break;
}
}
string QueryImp::eFunTostr(const FUNID eFnId)
{
string sFun = "";
switch(eFnId)
{
case FUNID_findObjectByIdInSameGroup:
{
sFun = "findObjectByIdInSameGroup";
}
break;
case FUNID_findObjectByIdInSameSet:
{
sFun = "findObjectByIdInSameSet";
}
break;
case FUNID_findObjectById4Any:
{
sFun = "findObjectById4All";
}
break;
case FUNID_findObjectById:
{
sFun = "findObjectById";
}
break;
case FUNID_findObjectById4All:
{
sFun = "findObjectById4All";
}
break;
case FUNID_findObjectByIdInSameStation:
{
sFun = "findObjectByIdInSameStation";
}
break;
default:
sFun = "UNKNOWN";
break;
}
return sFun;
}

View File

@ -0,0 +1,88 @@
#ifndef __QUERY_IMP_H__
#define __QUERY_IMP_H__
#include "servant/QueryF.h"
#include "DbHandle.h"
using namespace tars;
//////////////////////////////////////////////////////
enum FUNID
{
FUNID_findObjectById = 0,
FUNID_findObjectById4Any = 1,
FUNID_findObjectById4All = 2,
FUNID_findObjectByIdInSameGroup = 3,
FUNID_findObjectByIdInSameStation = 4,
FUNID_findObjectByIdInSameSet = 5
};
//////////////////////////////////////////////////////
/**
*
*/
class QueryImp: public QueryF
{
public:
/**
*
*/
QueryImp(){};
/**
*
*/
virtual void initialize();
/**
** 退
*/
virtual void destroy() {};
/**
* id获取所有该对象的活动endpoint列表
*/
virtual vector<EndpointF> findObjectById(const string & id, tars::CurrentPtr current);
/**
* id获取所有对象,
*/
virtual tars::Int32 findObjectById4Any(const std::string & id, vector<tars::EndpointF> &activeEp, vector<tars::EndpointF> &inactiveEp, tars::CurrentPtr current);
/**
* id获取对象所有endpoint列表
*/
Int32 findObjectById4All(const std::string & id, vector<tars::EndpointF> &activeEp, vector<tars::EndpointF> &inactiveEp, tars::CurrentPtr current);
/**
* id获取对象同组endpoint列表
*/
Int32 findObjectByIdInSameGroup(const std::string & id, vector<tars::EndpointF> &activeEp, vector<tars::EndpointF> &inactiveEp, tars::CurrentPtr current);
/**
* id获取对象指定归属地的endpoint列表
*/
Int32 findObjectByIdInSameStation(const std::string & id, const std::string & sStation, vector<tars::EndpointF> &activeEp, vector<tars::EndpointF> &inactiveEp, tars::CurrentPtr current);
/**
* id获取对象同set endpoint列表
*/
Int32 findObjectByIdInSameSet(const std::string & id,const std::string & setId,vector<tars::EndpointF> &activeEp,vector<tars::EndpointF> &inactiveEp, tars::CurrentPtr current);
private:
/**
*
*/
void doDaylog(const FUNID eFnId,const string& id,const vector<tars::EndpointF> &activeEp, const vector<tars::EndpointF> &inactiveEp, const tars::CurrentPtr& current,const std::ostringstream& os,const string& sSetid="");
/**
*
*/
string eFunTostr(const FUNID eFnId);
protected:
//数据库操作
CDbHandle _db;
};
#endif

View File

@ -0,0 +1,29 @@

#include "StatImp.h"
#include "../FrameworkServer.h"
///////////////////////////////////////////////////////////
//
int StatImp::reportMicMsg( const map<tars::StatMicMsgHead, tars::StatMicMsgBody>& statmsg,bool bFromClient, tars::CurrentPtr current )
{
// LOG_CONSOLE_DEBUG << "report---------------------------------access size:" << statmsg.size() << "|bFromClient:" <<bFromClient << endl;
if(bFromClient)
{
_clientStatData.push_back(statmsg);
}
else
{
_serverStatData.push_back(statmsg);
}
return 0;
}
int StatImp::reportSampleMsg(const vector<StatSampleMsg> &msg,tars::CurrentPtr current )
{
TLOGINFO("sample---------------------------------access size:" << msg.size() << endl);
return 0;
}

View File

@ -0,0 +1,60 @@

#ifndef __STAT_IMP_H_
#define __STAT_IMP_H_
#include <functional>
#include "util/tc_common.h"
#include "util/tc_thread.h"
#include "servant/RemoteLogger.h"
#include "servant/StatF.h"
using namespace tars;
class StatImp : public StatF
{
public:
/**
*
*/
StatImp()
{
}
~StatImp()
{
}
/**
*
*
* @return int
*/
virtual void initialize() {};
/**
* 退
*/
virtual void destroy()
{
}
/**
*
* @param statmsg,
* @return int, 0
*/
virtual int reportMicMsg( const map<tars::StatMicMsgHead, tars::StatMicMsgBody>& statmsg, bool bFromClient, tars::CurrentPtr current );
/**
*
* @param sample,
* @return int, 0
*/
virtual int reportSampleMsg(const vector<StatSampleMsg> &msg,tars::CurrentPtr current );
};
#endif

437
unit-test/server/hello.conf Executable file
View File

@ -0,0 +1,437 @@
<tars>
<application>
#proxy需要的配置
<client>
#地址
locator = TestApp.FrameworkServer.QueryObj@tcp -h 127.0.0.1 -p 11004
#最大超时时间(毫秒)
sync-invoke-timeout = 50000
async-invoke-timeout = 60000
#刷新端口时间间隔(毫秒)
refresh-endpoint-interval = 100000
#模块间调用[可选]
stat = TestApp.FrameworkServer.StatObj
#发送队列长度
sendqueuelimit = 1000000
#异步回调队列个数限制
asyncqueuecap = 1000000
#网络异步回调线程个数
asyncthread = 3
#网络线程个数
netthread = 2
#合并回调线程和网络线程(以网络线程个数为准)
mergenetasync = 0
#模块名称
modulename = TestApp.HelloServer
#server crt
ca = PROJECT_PATH/certs/server.crt
#can be empty
cert = PROJECT_PATH/certs/client.crt
#can be empty
key = PROJECT_PATH/certs/client.key
<TestApp.HelloServer.AuthObj>
#auth access key
accesskey = tars-test-user
#auth secret key
secretkey = 123456
</TestApp.HelloServer.AuthObj>
<TestApp.HelloServer.SSL1Obj>
#server crt
ca = PROJECT_PATH/certs/server1.crt
#can be empty
# cert = PROJECT_PATH/certs/client1.crt
#can be empty
# key = PROJECT_PATH/certs/client1.key
</TestApp.HelloServer.SSL1Obj>
<TestApp.HelloServer.SSL2Obj>
#server crt
ca = PROJECT_PATH/certs/server1.crt
#can be empty
cert = PROJECT_PATH/certs/client1.crt
#can be empty
key = PROJECT_PATH/certs/client1.key
</TestApp.HelloServer.SSL2Obj>
<TestApp.HelloServer.SSL3Obj>
#auth access key
accesskey = tars-test-user
#auth secret key
secretkey = 123456
#server crt
ca = PROJECT_PATH/certs/server1.crt
#can be empty
cert = PROJECT_PATH/certs/client1.crt
#can be empty
key = PROJECT_PATH/certs/client1.key
</TestApp.HelloServer.SSL3Obj>
</client>
#定义所有绑定的IP
<server>
start_output = ERROR
closecout = 0
#应用名称
app = TestApp
#服务名称
server = HelloServer
#服务的数据目录,可执行文件,配置文件等
basepath = .
datapath = .
#日志路径
logpath = .
#网络线程个数
netthread = 1
#合并网络和业务线程(以网络线程个数为准)
mergenetimp = 0
opencoroutine = 0
loglevel=TARS
#本地管理套接字[可选]
local = tcp -h 127.0.0.1 -p 18001 -t 10000
#配置中心的地址[可选]
config = TestApp.FrameworkServer.ConfigObj
#配置中心的地址[可选]
# notify = tars.tarsconfig.NotifyObj
#远程LogServer[可选]
log = TestApp.FrameworkServer.LogObj
# manuallisten = 1
#client crt, it can be empty when verifyclient is 0
# ca = PROJECT_PATH/certs/client.crt
cert = PROJECT_PATH/certs/server.crt
key = PROJECT_PATH/certs/server.key
ciphers =
#default is 0
verifyclient = 1
#配置绑定端口
<HelloAdapter>
#ip:port:timeout
#endpoint = tcp -h harbor.tars.com -p 45460 -t 60000
endpoint = tcp -h 127.0.0.1 -p 25460 -t 10000
#endpoint = udp -h * -p 45460 -t 60000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.HelloServer.HelloObj
#队列最大包个数
queuecap = 1000000
</HelloAdapter>
<TransAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 15460 -t 60000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.HelloServer.TransObj
#队列最大包个数
queuecap = 1000000
</TransAdapter>
<TransDstAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 15760 -t 60000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.HelloServer.TransDstObj
#队列最大包个数
queuecap = 1000000
</TransDstAdapter>
<TransWupAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 15461 -t 60000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.HelloServer.TransWupObj
#队列最大包个数
queuecap = 1000000
protocol = not-tars
</TransWupAdapter>
<HttpAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 8080 -t 60000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.HelloServer.HttpObj
#队列最大包个数
queuecap = 1000000
protocol = not-tars
</HttpAdapter>
<HttpsAdapter>
#ip:port:timeout
endpoint = ssl -h 127.0.0.1 -p 8081 -t 60000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.HelloServer.HttpsObj
#队列最大包个数
queuecap = 1000000
protocol = not-tars
</HttpsAdapter>
<Ipv6Adapter>
#ip:port:timeout
#endpoint = tcp -h fe80::9e5c:8eff:fe95:5cda%enp3s0 -p 25460 -t 10000
#endpoint = tcp -h fe80::9e5c:8eff:fe95:5cda%enp3s0 -p 25460 -t 10000
endpoint = tcp -h ::1 -p 25460 -t 60000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.HelloServer.Ipv6Obj
#队列最大包个数
queuecap = 1000000
</Ipv6Adapter>
<AuthObjAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 9016 -t 60000 -e 1
#allow ip
allow =
#max connection num
maxconns = 4096
#imp thread num
threads = 5
#servant
servant = TestApp.HelloServer.AuthObj
#queue capacity
queuecap = 1000000
#tars protocol
protocol = tars
accesskey=tars-test-user
secretkey=123456
</AuthObjAdapter>
<SSLHelloAdapter>
#ip:port:timeout
endpoint = ssl -h 127.0.0.1 -p 9005 -t 60000
#allow ip
allow =
#max connection num
maxconns = 4096
#imp thread num
threads = 5
#servant
servant = TestApp.HelloServer.SSLObj
#queue capacity
queuecap = 1000000
#tars protocol
protocol = tars
</SSLHelloAdapter>
<SSLHello1Adapter>
#ip:port:timeout
endpoint = ssl -h 127.0.0.1 -p 9006 -t 60000
#allow ip
allow =
#max connection num
maxconns = 4096
#imp thread num
threads = 5
#servant
servant = TestApp.HelloServer.SSL1Obj
#queue capacity
queuecap = 1000000
#tars protocol
protocol = tars
# ca = PROJECT_PATH/certs/client1.crt
cert = PROJECT_PATH/certs/server1.crt
key = PROJECT_PATH/certs/server1.key
#default is 0
verifyclient = 0
ciphers =
</SSLHello1Adapter>
<SSLHello2Adapter>
#ip:port:timeout
endpoint = ssl -h 127.0.0.1 -p 9007 -t 60000
#allow ip
allow =
#max connection num
maxconns = 4096
#imp thread num
threads = 5
#servant
servant = TestApp.HelloServer.SSL2Obj
#queue capacity
queuecap = 1000000
#tars protocol
protocol = tars
ca = PROJECT_PATH/certs/client1.crt
cert = PROJECT_PATH/certs/server1.crt
key = PROJECT_PATH/certs/server1.key
#default is 0
verifyclient = 1
ciphers =
</SSLHello2Adapter>
<SSLHello3Adapter>
#ip:port:timeout
endpoint = ssl -h 127.0.0.1 -p 9008 -t 60000 -e 1
#allow ip
allow =
#max connection num
maxconns = 4096
#imp thread num
threads = 5
#servant
servant = TestApp.HelloServer.SSL3Obj
#queue capacity
queuecap = 1000000
#tars protocol
protocol = tars
#auth access key
accesskey = tars-test-user
#auth secret key
secretkey = 123456
ca = PROJECT_PATH/certs/client1.crt
cert = PROJECT_PATH/certs/server1.crt
key = PROJECT_PATH/certs/server1.key
#default is 0
verifyclient = 1
ciphers =
</SSLHello3Adapter>
<CustomAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 9400 -t 60000
#allow ip
allow =
#max connection num
maxconns = 4096
#imp thread num
threads = 5
#servant
servant = TestApp.HelloServer.CustomObj
#queue capacity
queuecap = 1000000
#tars protocol
protocol = not_tars
</CustomAdapter>
<UdpObjAdapter>
#ip:port:timeout
endpoint = udp -h 127.0.0.1 -p 9016 -t 60000 -e 1
#allow ip
allow =
#max connection num
maxconns = 4096
#imp thread num
threads = 5
#servant
servant = TestApp.HelloServer.UdpObj
#queue capacity
queuecap = 1000000
#tars protocol
protocol = tars
</UdpObjAdapter>
<UdpIpv6Adapter>
#ip:port:timeout
endpoint = udp -h ::1 -p 25460 -t 60000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.HelloServer.UdpIpv6Obj
#队列最大包个数
queuecap = 1000000
</UdpIpv6Adapter>
<PushAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 9300 -t 60000
#allow ip
allow =
#max connection num
maxconns = 4096
#imp thread num
threads = 5
#servant
servant = TestApp.HelloServer.PushObj
#queue capacity
queuecap = 1000000
#tars protocol
protocol = not_tars
</PushAdapter>
<HelloTimeoutAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 25860 -t 5000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 1
#处理对象
servant = TestApp.HelloServer.HelloTimeoutObj
#队列最大包个数
queuecap = 1000000
#protocol = not-tars
</HelloTimeoutAdapter>
<HelloNoTimeoutAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 26460 -t 0
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 1
#处理对象
servant = TestApp.HelloServer.HelloNoTimeoutObj
#队列最大包个数
queuecap = 1000000
#protocol = not-tars
</HelloNoTimeoutAdapter>
</server>
</application>
</tars>

98
unit-test/server/rpc1.conf Executable file
View File

@ -0,0 +1,98 @@
<tars>
<application>
#proxy需要的配置
<client>
#地址
locator = TestApp.FrameworkServer.QueryObj@tcp -h 127.0.0.1 -p 11004
#最大超时时间(毫秒)
sync-invoke-timeout = 5000
async-invoke-timeout = 60000
#刷新端口时间间隔(毫秒)
refresh-endpoint-interval = 100000
#模块间调用[可选]
stat = tars.tarsstat.StatObj
#发送队列长度
sendqueuelimit = 1000000
#异步回调队列个数限制
asyncqueuecap = 1000000
#网络异步回调线程个数
asyncthread = 3
#网络线程个数
netthread = 2
#合并回调线程和网络线程(以网络线程个数为准)
mergenetasync = 0
#模块名称
modulename = TestApp.RpcServer
</client>
#定义所有绑定的IP
<server>
start_output = ERROR
closecout = 0
#应用名称
app = TestApp
#服务名称
server = RpcServer
#服务的数据目录,可执行文件,配置文件等
basepath = .
datapath = .
#日志路径
logpath = .
#网络线程个数
netthread = 1
#合并网络和业务线程(以网络线程个数为准)
mergenetimp = 0
opencoroutine = 0
loglevel=TARS
#本地管理套接字[可选]
# local = tcp -h 127.0.0.1 -p 15001 -t 10000
#本地node的ip:port:timeout[可选]
# node = ServerObj@tcp -h 127.0.0.1 -p 2345 -t 10000
#配置中心的地址[可选]
# config = tars.tarsconfig.ConfigObj
#配置中心的地址[可选]
# notify = tars.tarsconfig.NotifyObj
#远程LogServer[可选]
# log = tars.tarslog.LogObj
# manuallisten = 1
#配置绑定端口
<RpcAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 9990 -t 10000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.RpcServer.HelloObj
#队列最大包个数
queuecap = 1000000
#protocol = not-tars
</RpcAdapter>
<HttpAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 8180 -t 10000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.RpcServer.HttpObj
#队列最大包个数
queuecap = 1000000
protocol = not-tars
</HttpAdapter>
</server>
</application>
</tars>

98
unit-test/server/rpc2.conf Executable file
View File

@ -0,0 +1,98 @@
<tars>
<application>
#proxy需要的配置
<client>
#地址
locator = TestApp.FrameworkServer.QueryObj@tcp -h 127.0.0.1 -p 11004
#最大超时时间(毫秒)
sync-invoke-timeout = 5000
async-invoke-timeout = 60000
#刷新端口时间间隔(毫秒)
refresh-endpoint-interval = 100000
#模块间调用[可选]
stat = tars.tarsstat.StatObj
#发送队列长度
sendqueuelimit = 1000000
#异步回调队列个数限制
asyncqueuecap = 1000000
#网络异步回调线程个数
asyncthread = 3
#网络线程个数
netthread = 2
#合并回调线程和网络线程(以网络线程个数为准)
mergenetasync = 0
#模块名称
modulename = TestApp.RpcServer
</client>
#定义所有绑定的IP
<server>
start_output = ERROR
closecout = 0
#应用名称
app = TestApp
#服务名称
server = RpcServer
#服务的数据目录,可执行文件,配置文件等
basepath = .
datapath = .
#日志路径
logpath = .
#网络线程个数
netthread = 1
#合并网络和业务线程(以网络线程个数为准)
mergenetimp = 0
opencoroutine = 0
loglevel=TARS
#本地管理套接字[可选]
# local = tcp -h 127.0.0.1 -p 15001 -t 10000
#本地node的ip:port:timeout[可选]
# node = ServerObj@tcp -h 127.0.0.1 -p 2345 -t 10000
#配置中心的地址[可选]
# config = tars.tarsconfig.ConfigObj
#配置中心的地址[可选]
# notify = tars.tarsconfig.NotifyObj
#远程LogServer[可选]
# log = tars.tarslog.LogObj
# manuallisten = 1
#配置绑定端口
<RpcAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 9991 -t 10000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.RpcServer.HelloObj
#队列最大包个数
queuecap = 1000000
#protocol = not-tars
</RpcAdapter>
<HttpAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 8181 -t 10000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.RpcServer.HttpObj
#队列最大包个数
queuecap = 1000000
protocol = not-tars
</HttpAdapter>
</server>
</application>
</tars>

97
unit-test/server/rpc3.conf Executable file
View File

@ -0,0 +1,97 @@
<tars>
<application>
#proxy需要的配置
<client>
#地址
locator = TestApp.FrameworkServer.QueryObj@tcp -h 127.0.0.1 -p 11004
#最大超时时间(毫秒)
sync-invoke-timeout = 5000
async-invoke-timeout = 60000
#刷新端口时间间隔(毫秒)
refresh-endpoint-interval = 100000
#模块间调用[可选]
stat = tars.tarsstat.StatObj
#发送队列长度
sendqueuelimit = 1000000
#异步回调队列个数限制
asyncqueuecap = 1000000
#网络异步回调线程个数
asyncthread = 3
#网络线程个数
netthread = 2
#合并回调线程和网络线程(以网络线程个数为准)
mergenetasync = 0
#模块名称
modulename = TestApp.RpcServer
</client>
#定义所有绑定的IP
<server>
start_output = ERROR
closecout = 0
#应用名称
app = TestApp
#服务名称
server = RpcServer
#服务的数据目录,可执行文件,配置文件等
basepath = .
datapath = .
#日志路径
logpath = .
#网络线程个数
netthread = 1
#合并网络和业务线程(以网络线程个数为准)
mergenetimp = 0
opencoroutine = 0
loglevel=TARS
#本地管理套接字[可选]
# local = tcp -h 127.0.0.1 -p 15001 -t 10000
#本地node的ip:port:timeout[可选]
# node = ServerObj@tcp -h 127.0.0.1 -p 2345 -t 10000
#配置中心的地址[可选]
# config = tars.tarsconfig.ConfigObj
#配置中心的地址[可选]
# notify = tars.tarsconfig.NotifyObj
#远程LogServer[可选]
# log = tars.tarslog.LogObj
# manuallisten = 1
#配置绑定端口
<RpcAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 9992 -t 10000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.RpcServer.HelloObj
#队列最大包个数
queuecap = 1000000
#protocol = not-tars
</RpcAdapter>
<HttpAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 8182 -t 10000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.RpcServer.HttpObj
#队列最大包个数
queuecap = 1000000
protocol = not-tars
</HttpAdapter>
</server>
</application>
</tars>

View File

@ -0,0 +1,81 @@
<tars>
<application>
#proxy需要的配置
<client>
#地址
locator = TestApp.FrameworkServer.QueryObj@tcp -h 127.0.0.1 -p 11004
#最大超时时间(毫秒)
sync-invoke-timeout = 15000
async-invoke-timeout = 60000
#刷新端口时间间隔(毫秒)
refresh-endpoint-interval = 100000
#模块间调用[可选]
stat = TestApp.FrameworkServer.StatObj
#发送队列长度
sendqueuelimit = 1000000
#异步回调队列个数限制
asyncqueuecap = 1000000
#网络异步回调线程个数
asyncthread = 3
#网络线程个数
netthread = 1
#合并回调线程和网络线程(以网络线程个数为准)
mergenetasync = 0
#模块名称
modulename = TestApp.WinServer
</client>
#定义所有绑定的IP
<server>
start_output = ERROR
closecout = 0
#应用名称
app = TestApp
#服务名称
server = WinServer
#服务的数据目录,可执行文件,配置文件等
basepath = .
datapath = .
#日志路径
logpath = .
#网络线程个数
netthread = 1
#合并网络和业务线程(以网络线程个数为准)
mergenetimp = 0
opencoroutine = 0
loglevel=TARS
#本地管理套接字[可选]
local = tcp -h 127.0.0.1 -p 15001 -t 10000
#配置中心的地址[可选]
config = TestApp.FrameworkServer.ConfigObj
#配置中心的地址[可选]
# notify = tars.tarsconfig.NotifyObj
#远程LogServer[可选]
# log = tars.tarslog.LogObj
# manuallisten = 1
#配置绑定端口
<WinAdapter>
#ip:port:timeout
endpoint = tcp -h 127.0.0.1 -p 18809 -t 10000
#允许的IP地址
allow =
#最大连接数
maxconns = 4096
#当前线程个数
threads = 5
#处理对象
servant = TestApp.WinServer.WinObj
#队列最大包个数
queuecap = 1000000
#protocol = not-tars
</WinAdapter>
</server>
</application>
</tars>

View File

@ -0,0 +1,411 @@
//
// Created by jarod on 2021/6/7.
//
#ifndef TARS_CPP_TEST_SERVER_H
#define TARS_CPP_TEST_SERVER_H
#include "util/tc_network_buffer.h"
#include "util/tc_epoll_server.h"
#include "util/tc_openssl.h"
#include "certs.h"
using namespace tars;
class MyTcpServer;
static TC_NetWorkBuffer::PACKET_TYPE parseLine(TC_NetWorkBuffer&in, vector<char> &out)
{
try
{
if(in.empty())
{
return TC_NetWorkBuffer::PACKET_LESS;
}
const char *data = in.mergeBuffers();
const char *p = TC_Port::strnstr(data, "\r\n", in.getBufferLength());
if(NULL == p)
{
return TC_NetWorkBuffer::PACKET_LESS;
}
size_t length = p - data;
out.resize(length+2);
memcpy(&out[0], data, length+2);
in.moveHeader(length + 2);
return TC_NetWorkBuffer::PACKET_FULL;
}
catch (exception &ex)
{
return TC_NetWorkBuffer::PACKET_ERR;
}
return TC_NetWorkBuffer::PACKET_LESS; //表示收到的包不完全
}
/**
* , 线
*/
class TcpHandle : public TC_EpollServer::Handle
{
public:
/**
*
*/
virtual void initialize()
{
_server = (MyTcpServer*)(getEpollServer());
}
/**
*
*/
virtual void handle(const shared_ptr<TC_EpollServer::RecvContext> &data)
{
try
{
shared_ptr<TC_EpollServer::SendContext> send = data->createSendContext();
// LOG_CONSOLE_DEBUG << TC_Thread::CURRENT_THREADID() << ", handle:" << string(data->buffer().data(), data->buffer().size()) << endl;
send->buffer()->setBuffer(data->buffer());
sendResponse(send);
}
catch (exception &ex)
{
close(data);
}
}
virtual void handleClose(const shared_ptr<TC_EpollServer::RecvContext> &data)
{
// LOG_CONSOLE_DEBUG << "use count:" << data.use_count() << endl;
}
protected:
MyTcpServer *_server;
};
/**
* , 线
*/
class TcpQueueHandle : public TC_EpollServer::Handle
{
public:
/**
*
*/
virtual void initialize()
{
_server = (MyTcpServer*)(getEpollServer());
}
/**
*
*/
virtual void handle(const shared_ptr<TC_EpollServer::RecvContext> &data)
{
try
{
shared_ptr<TC_EpollServer::SendContext> send = data->createSendContext();
string buff(data->buffer().data(), data->buffer().size());
buff += "-" + TC_Common::tostr(TC_Thread::CURRENT_THREADID());
send->buffer()->setBuffer(buff);
sendResponse(send);
}
catch (exception &ex)
{
close(data);
}
}
protected:
MyTcpServer *_server;
};
class MyTcpServer
{
public:
MyTcpServer()
{
_epollServer = new TC_EpollServer();
};
void initialize()
{
}
#if TARS_SSL
void bindSSL(const std::string &str, int maxConnections = 10240)
{
TC_EpollServer::BindAdapterPtr lsPtr = _epollServer->createBindAdapter<TcpHandle>("SSLAdapter", str, 5);
//设置最大连接数
lsPtr->setMaxConns(maxConnections);
//设置协议解析器
lsPtr->setProtocol(TC_NetWorkBuffer::parseEcho);
bool verifyClient = false;
string ciphers = "";
shared_ptr<TC_OpenSSL::CTX> ctx = TC_OpenSSL::newCtx(CA, SERVER_CERT, SERVER_KEY, verifyClient, ciphers);
assert(ctx);
lsPtr->setSSLCtx(ctx);
//绑定对象
_epollServer->bind(lsPtr);
}
#endif
void bindUdp(const std::string &str, int maxConnections = 10240)
{
TC_EpollServer::BindAdapterPtr lsPtr = _epollServer->createBindAdapter<TcpHandle>("UdpAdapter", str, 2);
//设置最大连接数
lsPtr->setMaxConns(maxConnections);
//设置协议解析器
lsPtr->setProtocol(TC_NetWorkBuffer::parseEcho);
//绑定对象
_epollServer->bind(lsPtr);
}
void bindManualTcp(const std::string &str, int maxConnections = 10240)
{
TC_EpollServer::BindAdapterPtr lsPtr = _epollServer->createBindAdapter<TcpHandle>("TcpManualAdapter", str, 5);
//设置最大连接数
lsPtr->setMaxConns(maxConnections);
//设置协议解析器
lsPtr->setProtocol(TC_NetWorkBuffer::parseEcho);
lsPtr->enableManualListen();
//绑定对象
_epollServer->bind(lsPtr);
}
void startManualListen()
{
_epollServer->getBindAdapter("TcpManualAdapter")->manualListen();
}
void cancelManualListen()
{
_epollServer->getBindAdapter("TcpManualAdapter")->cancelListen();
}
void bindTcp(const std::string &str, int maxConnections = 10240)
{
TC_EpollServer::BindAdapterPtr lsPtr = _epollServer->createBindAdapter<TcpHandle>("TcpAdapter", str, 5);
//设置最大连接数
lsPtr->setMaxConns(maxConnections);
//设置协议解析器
lsPtr->setProtocol(TC_NetWorkBuffer::parseEcho);
//绑定对象
_epollServer->bind(lsPtr);
}
void bindTcpLine(const std::string &str, int maxConnections = 10240)
{
TC_EpollServer::BindAdapterPtr lsPtr = _epollServer->createBindAdapter<TcpHandle>("TcpLineAdapter", str, 5);
//设置最大连接数
lsPtr->setMaxConns(maxConnections);
//设置协议解析器
lsPtr->setProtocol(parseLine);
//绑定对象
_epollServer->bind(lsPtr);
}
void bindTcpQueue(const std::string &str)
{
TC_EpollServer::BindAdapterPtr lsPtr = _epollServer->createBindAdapter<TcpQueueHandle>("TcpQueueAdapter", str, 5);
lsPtr->enableQueueMode();
//设置最大连接数
lsPtr->setMaxConns(10240);
//设置协议解析器
lsPtr->setProtocol(TC_NetWorkBuffer::parseEcho);
//绑定对象
_epollServer->bind(lsPtr);
}
void waitForShutdown()
{
_start = new std::thread([=]{
_epollServer->waitForShutdown();
});
TC_Common::msleep(100);
}
void terminate()
{
_epollServer->terminate();
_start->join();
delete _start;
delete _epollServer;
}
std::thread *_start;
TC_EpollServer *_epollServer;
};
class MyHttpServer;
/**
* , 线
*/
class HttpHandle : public TC_EpollServer::Handle
{
public:
/**
*
*/
virtual void initialize()
{
_server = (MyHttpServer*)(getEpollServer());
}
/**
*
*/
virtual void handle(const shared_ptr<TC_EpollServer::RecvContext> &data)
{
try
{
TC_HttpRequest request;
request.decode(data->buffer().data(), data->buffer().size());
// cout << "-------------------------------------------------------" << endl;
// cout << "request: " << string(data->buffer().data(), data->buffer().size()) << endl;
// cout << "-------------------------------------------------------" << endl;
TC_HttpResponse response;
response.setConnection("close");
response.setResponse(200, "OK", request.getContent());
string buffer = response.encode();
shared_ptr<TC_EpollServer::SendContext> send = data->createSendContext();
send->buffer()->setBuffer(buffer.c_str(), buffer.size());
sendResponse(send);
}
catch (exception &ex)
{
close(data);
}
}
protected:
MyHttpServer *_server;
};
class MyHttpServer
{
public:
MyHttpServer()
{
_epollServer = new TC_EpollServer();
};
void initialize()
{
}
void bindHttp(const std::string &str)
{
TC_EpollServer::BindAdapterPtr lsPtr = _epollServer->createBindAdapter<HttpHandle>("HttpAdapter", str, 5); //new TC_EpollServer::BindAdapter(_epollServer);
//设置最大连接数
lsPtr->setMaxConns(1024);
//设置协议解析器
lsPtr->setProtocol(TC_NetWorkBuffer::parseHttp);
//绑定对象
_epollServer->bind(lsPtr);
}
#if TARS_SSL
void bindHttpSSL(const std::string &str)
{
TC_EpollServer::BindAdapterPtr lsPtr = _epollServer->createBindAdapter<HttpHandle>("HttpsAdapter", str, 5);
//设置最大连接数
lsPtr->setMaxConns(1024);
//设置协议解析器
lsPtr->setProtocol(TC_NetWorkBuffer::parseHttp);
bool verifyClient = false;
string ciphers = "";
shared_ptr<TC_OpenSSL::CTX> ctx = TC_OpenSSL::newCtx(CA, SERVER_CERT, SERVER_KEY, verifyClient, ciphers);
lsPtr->setSSLCtx(ctx);
//绑定对象
_epollServer->bind(lsPtr);
}
void bindHttpSSLVerify(const std::string &str)
{
TC_EpollServer::BindAdapterPtr lsPtr = _epollServer->createBindAdapter<HttpHandle>("HttpsVerifyAdapter", str, 5);
//设置最大连接数
lsPtr->setMaxConns(1024);
//设置协议解析器
lsPtr->setProtocol(TC_NetWorkBuffer::parseHttp);
bool verifyClient = true;
string ciphers = "";
shared_ptr<TC_OpenSSL::CTX> ctx = TC_OpenSSL::newCtx(CLIENT_CERT, SERVER_CERT, SERVER_KEY, verifyClient, ciphers);
lsPtr->setSSLCtx(ctx);
//绑定对象
_epollServer->bind(lsPtr);
}
#endif
void waitForShutdown()
{
_start = new std::thread([=]{
_epollServer->waitForShutdown();
});
}
void terminate()
{
_epollServer->terminate();
_start->join();
delete _start;
}
std::thread *_start;
TC_EpollServer *_epollServer;
};
#endif //TARS_CPP_TEST_SERVER_H

195
unit-test/util/test_tc_cas.cpp Executable file
View File

@ -0,0 +1,195 @@
#include "util/tc_common.h"
#include "util/tc_cas_queue.h"
#include "util/tc_thread.h"
#include "util/tc_autoptr.h"
#include "util/tc_spin_lock.h"
#include "util/tc_thread_queue.h"
#include "gtest/gtest.h"
#include <mutex>
#include <iostream>
using namespace tars;
class UtilCasTest : public testing::Test
{
public:
//添加日志
static void SetUpTestCase()
{
// cout<<"SetUpTestCase"<<endl;
}
static void TearDownTestCase()
{
// cout<<"TearDownTestCase"<<endl;
}
virtual void SetUp() //TEST跑之前会执行SetUp
{
// cout<<"SetUp"<<endl;
}
virtual void TearDown() //TEST跑完之后会执行TearDown
{
// cout<<"TearDown"<<endl;
}
};
TEST_F(UtilCasTest, casLock)
{
size_t i=0;
size_t count = 1000000;
TC_SpinLock mutex;
std::thread add([&]{
int j = count;
while(j--) {
TC_LockT<TC_SpinLock> lock(mutex);
++i;
}
});
std::thread del([&]{
int j = count;
while(j--) {
TC_LockT<TC_SpinLock> lock(mutex);
--i;
}
});
add.join();
del.join();
ASSERT_TRUE(i == 0);
}
bool g_terminate = false;
TC_CasQueue<int64_t> data_cas;
TC_ThreadQueue<int64_t> data_queue;
class WriteThread : public TC_Thread
{
protected:
virtual void run()
{
for(int64_t i = 0; i < 100000; i++) {
data_cas.push_back(i);
}
}
};
class ReadThread : public TC_Thread, public TC_HandleBase
{
public:
ReadThread() {}
virtual void run()
{
int64_t last = -1;
while(!g_terminate) {
int64_t i;
if(data_cas.pop_front(i))
{
ASSERT_TRUE(i - last == 1);
last = i;
if(i == 100000-1)
{
g_terminate = true;
}
}
}
}
};
TEST_F(UtilCasTest, casQueue)
{
WriteThread w;
ReadThread r;
w.start();
r.start();
w.join();
r.join();
}
template<typename Q>
void start(int w, int r, int sleeps, Q &queue_data)
{
g_terminate = false;
atomic<int64_t> writeIndex {0};
vector<std::thread*> wthreads;
for(int i = 0 ; i < w; i++) {
wthreads.push_back(new std::thread([&]
{
while(!g_terminate)
{
queue_data.push_back(++writeIndex);
}
}));
}
int64_t readIndex = 0;
vector<std::thread*> rthreads;
for(int i = 0 ; i < r; i++)
{
rthreads.push_back(new std::thread([&]{
do{
int64_t j;
if(queue_data.pop_front(j))
{
readIndex = j;
}
else
{
if(sleeps > 0)
{
TC_Common::msleep(sleeps);
}
}
}while(!g_terminate);
}));
}
std::thread print([&]{
int64_t lastReadIndex = 0;
int64_t lastWriteIndex = 0;
while(!g_terminate) {
cout << "size:" << data_queue.size() << ", write/read index:" << writeIndex/10000. << "/" << readIndex/10000. << ", " << (writeIndex-lastWriteIndex)/10000. << ", " << (readIndex - lastReadIndex)/10000. << endl;
lastReadIndex = readIndex;
lastWriteIndex = writeIndex;
TC_Common::sleep(1);
}
});
std::thread t([&]{
TC_Common::sleep(10);
g_terminate = true;
});
t.join();
print.join();
for(size_t i = 0; i < wthreads.size(); i++)
{
wthreads[i]->join();
delete wthreads[i];
}
for(size_t i = 0; i < rthreads.size(); i++)
{
rthreads[i]->join();
delete rthreads[i];
}
}
int wThread = 1;
int rThread = 4;
int sleepms = 0;
TEST_F(UtilCasTest, queueBatch)
{
cout << "threadQueueBatch-------------------------------------------" << endl;
start<TC_ThreadQueue<int64_t>>(wThread, rThread, sleepms, data_queue);
cout << "casQueueBatch-------------------------------------------" << endl;
start<TC_CasQueue<int64_t>>(wThread, rThread, sleepms, data_cas);
}

View File

@ -0,0 +1,371 @@
//
// Created by jarod on 2020/2/20.
//
#include "util/tc_coroutine.h"
#include "util/tc_coroutine_queue.h"
#include "util/tc_thread.h"
#include "gtest/gtest.h"
using namespace tars;
class UtilCoroutineTest : public testing::Test
{
public:
//添加日志
static void SetUpTestCase()
{
// cout<<"SetUpTestCase"<<endl;
}
static void TearDownTestCase()
{
// cout<<"TearDownTestCase"<<endl;
}
virtual void SetUp() //TEST跑之前会执行SetUp
{
// cout<<"SetUp"<<endl;
}
virtual void TearDown() //TEST跑完之后会执行TearDown
{
// cout<<"TearDown"<<endl;
}
};
class CoSleepThread : public TC_Thread
{
public:
CoSleepThread() {}
virtual void run()
{
int64_t at = TC_Common::now2ms();
int64_t lt = 0;
_scheduler->sleep(100);
lt = TC_Common::now2ms();
ASSERT_TRUE(lt - at >= 100 && lt - at <= 106);
at = lt;
_scheduler->sleep(100);
lt = TC_Common::now2ms();
ASSERT_TRUE(lt - at >= 100 && lt - at <= 106);
at = lt;
_scheduler->sleep(100);
lt = TC_Common::now2ms();
ASSERT_TRUE(lt - at >= 100 && lt - at <= 106);
}
};
class CoYieldThread : public TC_Thread
{
public:
CoYieldThread() {}
virtual void run()
{
int64_t lt, at;
int coroId = this->getScheduler()->getCoroutineId();
{
std::thread check([&]()
{
TC_Common::msleep(500);
this->_scheduler->put(coroId);
});
at = TC_Common::now2ms();
lt = 0;
_scheduler->yield(false);
lt = TC_Common::now2ms();
ASSERT_TRUE(lt - at >= 500 && lt - at <= 506);
check.join();
}
{
std::thread check([&]()
{
TC_Common::msleep(500);
this->_scheduler->notify();
});
at = lt;
_scheduler->yield(true);
lt = TC_Common::now2ms();
ASSERT_TRUE(lt - at >= 500 && lt - at <= 506);
check.join();
}
}
};
bool CoThreadDo = false;
class CoThread : public TC_Thread
{
public:
CoThread() {}
virtual void run()
{
CoThreadDo = true;
cout << "in coroutine" << endl;
}
};
TEST_F(UtilCoroutineTest, CoThread)
{
CoThreadDo = false;
CoThread* a = new CoThread();
a->startCoroutine(10, 128*1024, true);
a->getThreadControl().join();
ASSERT_TRUE(CoThreadDo);
delete a;
}
class CoThread1 : public TC_Thread
{
public:
CoThread1() {}
virtual void run()
{
TC_CoroutineScheduler::scheduler()->go(std::bind(&CoThread1::doCo, this));
LOG_CONSOLE_DEBUG << "in coroutine" << endl;
}
void doCo()
{
CoThreadDo = true;
LOG_CONSOLE_DEBUG << "in coroutine" << endl;
}
};
TEST_F(UtilCoroutineTest, CoThread1)
{
CoThreadDo = false;
CoThread1* a = new CoThread1();
a->startCoroutine(10, 128*1024, true);
a->getThreadControl().join();
ASSERT_TRUE(CoThreadDo);
delete a;
}
class CoAThread : public TC_Thread
{
public:
CoAThread(TC_CoroutineQueue<int> * data): _queue(data) {}
virtual void run()
{
for(int i = 0; i < 100; i++) {
_queue->push_back(i);
_scheduler->sleep(10);
}
}
TC_CoroutineQueue<int> *_queue;
};
class CoBThread : public TC_Thread
{
public:
CoBThread(TC_CoroutineQueue<int> * data): _queue(data) {}
virtual void run()
{
_queue->exec([&](int i) {
if(_last != -1) {
ASSERT_TRUE(_last + 1 == i);
}
_last = i;
});
}
int _last = -1;
TC_CoroutineQueue<int> *_queue;
};
TEST_F(UtilCoroutineTest, coThreadQuit)
{
TC_CoroutineQueue<int> * data = new TC_CoroutineQueue<int>();
CoAThread* a = new CoAThread(data);
a->startCoroutine(10, 128*1024, true);
a->getThreadControl().join();
ASSERT_TRUE(data->size() == 100);
delete data;
delete a;
}
TEST_F(UtilCoroutineTest, coThread)
{
TC_CoroutineQueue<int> * data = new TC_CoroutineQueue<int>();
CoAThread* a = new CoAThread(data);
a->startCoroutine(10, 128*1024, false);
std::thread start([=]{
TC_Common::sleep(2);
ASSERT_TRUE(data->size() == 100 );
a->getScheduler()->terminate();
});
a->getThreadControl().join();
start.join();
delete data;
delete a;
}
TEST_F(UtilCoroutineTest, coQueue)
{
TC_CoroutineQueue<int> * data = new TC_CoroutineQueue<int>();
CoAThread* a = new CoAThread(data);
CoBThread* b = new CoBThread(data);
a->startCoroutine(10, 128*1024, true);
b->startCoroutine(10, 128*1024, true);
a->getThreadControl().join();
b->_queue->terminate();
b->getThreadControl().join();
delete data;
delete a;
delete b;
}
TEST_F(UtilCoroutineTest, sleep)
{
CoSleepThread* a = new CoSleepThread();
a->startCoroutine(10, 128*1024, true);
a->getThreadControl().join();
delete a;
}
TEST_F(UtilCoroutineTest, yield)
{
CoYieldThread* a = new CoYieldThread();
a->startCoroutine(10, 128*1024, true);
a->getThreadControl().join();
delete a;
}
TEST_F(UtilCoroutineTest, aliveQuit)
{
CoSleepThread* a = new CoSleepThread();
a->startCoroutine(10, 128*1024, true);
TC_Common::msleep(100);
ASSERT_TRUE(a->isAlive());
a->getThreadControl().join();
delete a;
}
TEST_F(UtilCoroutineTest, alive)
{
CoSleepThread* a = new CoSleepThread();
a->startCoroutine(10, 128*1024, false);
TC_Common::msleep(200);
ASSERT_TRUE(a->isAlive());
a->getScheduler()->terminate();
a->getThreadControl().join();
delete a;
}
class MyCoroutine : public TC_Coroutine
{
protected:
void handle()
{
++_count;
this->go(std::bind(&MyCoroutine::co_test, this));
}
void co_test()
{
++_count;
}
public:
static atomic<int> _count;
};
atomic<int> MyCoroutine::_count{0};
TEST_F(UtilCoroutineTest, coCoroutine)
{
MyCoroutine::_count = 0;
MyCoroutine co;
co.setCoroInfo(10, 200, 128*1024);
co.start();
co.join();
ASSERT_TRUE(MyCoroutine::_count == 20);
}
TEST_F(UtilCoroutineTest, coCoroutineQuit)
{
std::thread cor_call([&]()
{
auto scheduler = TC_CoroutineScheduler::create();
scheduler->go([&]()
{
scheduler->setNoCoroutineCallback([=](TC_CoroutineScheduler* s)
{
s->terminate();
});
TC_Common::msleep(100);
});
scheduler->run();
});
cor_call.join();
}

View File

@ -0,0 +1,40 @@
//
// Created by jarod on 2020/2/20.
//
#include "util/tc_encoder.h"
#include "gtest/gtest.h"
#include "util/tc_common.h"
using namespace tars;
class UtilEncodeTest : public testing::Test
{
public:
//添加日志
static void SetUpTestCase()
{
}
static void TearDownTestCase()
{
}
virtual void SetUp() //TEST跑之前会执行SetUp
{
}
virtual void TearDown() //TEST跑完之后会执行TearDown
{
}
};
TEST_F(UtilEncodeTest, encode) //此时使用的是TEST_F宏
{
string utf8="我们的祖国;";
string gbk;
gbk = TC_Encoder::utf82gbk(utf8);//, TC_Encoder::ICONV_NORMAL);
string tmpUtf8 = TC_Encoder::gbk2utf8(gbk);//, TC_Encoder::ICONV_NORMAL);
ASSERT_TRUE(utf8 == tmpUtf8);
}

View File

@ -0,0 +1,295 @@
#include "util/tc_epoller.h"
#include "util/tc_common.h"
#include "util/tc_logger.h"
#include <thread>
#include <iostream>
#include "gtest/gtest.h"
using namespace tars;
class UtilEpollTest : public testing::Test
{
public:
//添加日志
static void SetUpTestCase()
{
// cout<<"SetUpTestCase"<<endl;
}
static void TearDownTestCase()
{
// cout<<"TearDownTestCase"<<endl;
}
virtual void SetUp() //TEST跑之前会执行SetUp
{
// cout<<"SetUp"<<endl;
}
virtual void TearDown() //TEST跑完之后会执行TearDown
{
// cout<<"TearDown"<<endl;
}
};
TEST_F(UtilEpollTest, OUTEvents)
{
TC_Epoller epoller;
epoller.create(1024);
//用udp句柄, 方便唤醒, tcp句柄还得构建连接后才能唤醒
TC_Socket fd;
fd.createSocket(SOCK_DGRAM, AF_INET);
shared_ptr<TC_Epoller::EpollInfo> epollInfo = epoller.createEpollInfo(fd.getfd());
int out = 0;
map<uint32_t, TC_Epoller::EpollInfo::EVENT_CALLBACK> callbacks;
callbacks[EPOLLOUT] = [&](const shared_ptr<TC_Epoller::EpollInfo> &epollInfo){
++out;
return true;
};
epollInfo->registerCallback(callbacks, EPOLLIN | EPOLLOUT);
std::thread start([&]{
TC_Common::msleep(5);
int i = 100;
while(i--) {
int l = out;
epollInfo->mod(EPOLLOUT);
TC_Common::msleep(5);
ASSERT_TRUE(out - l == 1);
}
TC_Common::msleep(5);
epoller.terminate();
});
epoller.loop(1000);
// delete epollInfo;
start.join();
}
TEST_F(UtilEpollTest, close)
{
TC_Epoller epoller;
epoller.create(1024);
//用udp句柄, 方便唤醒, tcp句柄还得构建连接后才能唤醒
TC_Socket fd;
fd.createSocket(SOCK_DGRAM, AF_INET);
bool c = false;
{
shared_ptr<TC_Epoller::EpollInfo> epollInfo = epoller.createEpollInfo(fd.getfd());
map<uint32_t, TC_Epoller::EpollInfo::EVENT_CALLBACK> callbacks;
callbacks[EPOLLOUT] = [&](const shared_ptr<TC_Epoller::EpollInfo>& epollInfo)
{
return false;
};
epollInfo->registerCallback(callbacks, 0);
epollInfo->cookie(&c, [&](void* p)
{
ASSERT_TRUE(c == false);
c = true;
ASSERT_TRUE(&c == p);
});
std::thread start([&]
{
TC_Common::msleep(20);
epollInfo->add(EPOLLOUT);
TC_Common::msleep(100);
epoller.terminate();
});
epoller.loop(1000);
start.join();
// LOG_CONSOLE_DEBUG << epollInfo.use_count() << endl;
epollInfo.reset();
}
ASSERT_TRUE(c);
}
TEST_F(UtilEpollTest, notify)
{
TC_Epoller epoller;
epoller.create(1024);
//用udp句柄, 方便唤醒, tcp句柄还得构建连接后才能唤醒
TC_Socket fd;
fd.createSocket(SOCK_DGRAM, AF_INET);
bool idle = false;
epoller.idle([&]{
idle = true;
});
std::thread start([&]{
TC_Common::msleep(5);
epoller.notify();
TC_Common::msleep(5);
ASSERT_TRUE(idle);
epoller.terminate();
});
epoller.loop(10000);
start.join();
}
class EpollClass
{
public:
~EpollClass()
{
}
void test()
{
_data.push_back(std::make_pair(TNOWMS, 0));
}
vector<pair<int64_t, int64_t>> _data;
};
TEST_F(UtilEpollTest, testEpollTimer)
{
TC_Epoller epoller;
epoller.create(1024);
shared_ptr<EpollClass> tPtr = std::make_shared<EpollClass>();
std::thread start([&]{
epoller.postRepeated(100, false, std::bind(&EpollClass::test, tPtr.get()));
TC_Common::msleep(1120);
epoller.terminate();
ASSERT_TRUE(tPtr->_data.size() >= 10);
ASSERT_TRUE(tPtr->_data.size() <= 11);
for(int i = 0; i < 9; i++) {
//注意毫秒的精度问题
ASSERT_TRUE(fabs(tPtr->_data[i+1].first - tPtr->_data[i].first) <= 120);
}
});
epoller.loop(200);
start.join();
}
TEST_F(UtilEpollTest, testDelayTask)
{
TC_Timer timer;
timer.startTimer(1);
shared_ptr<EpollClass> tPtr = std::make_shared<EpollClass>();
timer.postDelayed(50, std::bind(&EpollClass::test, tPtr.get()));
timer.postDelayed(100, std::bind(&EpollClass::test, tPtr.get()));
timer.postDelayed(200, std::bind(&EpollClass::test, tPtr.get()));
TC_Common::msleep(306);
ASSERT_TRUE(tPtr->_data.size() == 3);
timer.stopTimer();
}
TEST_F(UtilEpollTest, testSharePtr)
{
TC_Timer timer;
timer.startTimer(1);
shared_ptr<EpollClass> tPtr = std::make_shared<EpollClass>();
timer.postDelayed(50, std::bind(&EpollClass::test, tPtr));
TC_Common::msleep(306);
LOG_CONSOLE_DEBUG << tPtr->_data.size() << endl;
ASSERT_TRUE(tPtr->_data.size() == 1);
timer.stopTimer();
}
TEST_F(UtilEpollTest, testEpollSyncCallback)
{
TC_Epoller epoller;
epoller.create(1024);
shared_ptr<EpollClass> tPtr = std::make_shared<EpollClass>();
std::thread start([&]{
TC_Common::msleep(100);
epoller.syncCallback([&](){
tPtr->test();
});
ASSERT_TRUE(tPtr->_data.size() == 1);
epoller.terminate();
});
epoller.loop(200);
start.join();
}
TEST_F(UtilEpollTest, testEpollAsyncCallback)
{
TC_Epoller epoller;
epoller.create(1024);
shared_ptr<EpollClass> tPtr = std::make_shared<EpollClass>();
std::thread start([&]{
TC_Common::msleep(100);
epoller.asyncCallback([&](){
tPtr->test();
});
TC_Common::msleep(100);
epoller.terminate();
ASSERT_TRUE(tPtr->_data.size() == 1);
});
epoller.loop(200);
start.join();
}

View File

@ -0,0 +1,285 @@
#include "util/tc_common.h"
#include <thread>
#include "gtest/gtest.h"
#include "test_server.h"
using namespace tars;
static TC_Endpoint TEST_HOST_EP("tcp -h 127.0.0.1 -p 19089 -t 10000");
static TC_Endpoint LINE_HOST_EP("tcp -h 127.0.0.1 -p 19099 -t 10000");
static TC_Endpoint QUEUE_HOST_EP("tcp -h 127.0.0.1 -p 19019 -t 10000");
static TC_Endpoint UDP_HOST_EP("udp -h 127.0.0.1 -p 18085 -t 10000");
class UtilEpollServerTest : public testing::Test
{
public:
//添加日志
static void SetUpTestCase()
{
}
static void TearDownTestCase()
{
}
virtual void SetUp()
{
}
virtual void TearDown() //TEST跑完之后会执行TearDown
{
}
void startServer(MyTcpServer &server, TC_EpollServer::SERVER_OPEN_COROUTINE openCoroutine)
{
server.initialize();
server._epollServer->setOpenCoroutine(openCoroutine);
server.bindUdp(UDP_HOST_EP.toString());
server.bindTcp(TEST_HOST_EP.toString(), 10);
server.bindTcpLine(LINE_HOST_EP.toString(), 10);
server.bindTcpQueue(QUEUE_HOST_EP.toString());
server.waitForShutdown();
}
void startManualServer(MyTcpServer &server, TC_EpollServer::SERVER_OPEN_COROUTINE openCoroutine)
{
server.initialize();
server._epollServer->setOpenCoroutine(openCoroutine);
server.bindManualTcp(TEST_HOST_EP.toString(), 10);
server.waitForShutdown();
}
void stopServer(MyTcpServer &server)
{
server.terminate();
}
protected:
};
TEST_F(UtilEpollServerTest, RunUdp)
{
for(int i = 0; i <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; i++)
{
MyTcpServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE)i);
TC_UDPClient client(UDP_HOST_EP.getHost(), UDP_HOST_EP.getPort(), UDP_HOST_EP.getTimeout());
int iRet = 0;
char recvBuffer[1024];
size_t recvLenth = 1024;
for (int i = 0; i < 10; i++)
{
iRet = client.sendRecv("abc", 3, recvBuffer, recvLenth);
ASSERT_TRUE(iRet == 0);
ASSERT_TRUE(string(recvBuffer, recvLenth) == "abc");
}
stopServer(server);
}
}
TEST_F(UtilEpollServerTest, RunTcp)
{
for(int i = 0; i <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; i++)
{
MyTcpServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE)i);
TC_TCPClient client(TEST_HOST_EP.getHost(), TEST_HOST_EP.getPort(), TEST_HOST_EP.getTimeout());
int iRet = 0;
char recvBuffer[1024];
size_t recvLenth = 1024;
for (int i = 0; i < 10; i++) {
iRet = client.sendRecv("abc", 3, recvBuffer, recvLenth);
ASSERT_TRUE(iRet == 0);
ASSERT_TRUE(string(recvBuffer, recvLenth) == "abc");
}
stopServer(server);
}
}
TEST_F(UtilEpollServerTest, RunEnableManualListen)
{
int i = 0;
for(int i = 0; i <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; i++)
{
MyTcpServer server;
startManualServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE)i);
TC_TCPClient client(TEST_HOST_EP.getHost(), TEST_HOST_EP.getPort(), TEST_HOST_EP.getTimeout());
int iRet = 0;
char recvBuffer[1024];
size_t recvLenth = 1024;
iRet = client.sendRecv("abc", 3, recvBuffer, recvLenth);
ASSERT_TRUE(iRet == -6);
server.startManualListen();
iRet = client.sendRecv("abc", 3, recvBuffer, recvLenth);
ASSERT_TRUE(iRet == 0);
ASSERT_TRUE(string(recvBuffer, recvLenth) == "abc");
server.cancelManualListen();
iRet = client.sendRecv("abc", 3, recvBuffer, recvLenth);
ASSERT_TRUE(iRet != TC_ClientSocket::EM_SUCCESS);
server.startManualListen();
iRet = client.sendRecv("abc", 3, recvBuffer, recvLenth);
ASSERT_TRUE(iRet == 0);
ASSERT_TRUE(string(recvBuffer, recvLenth) == "abc");
stopServer(server);
}
}
TEST_F(UtilEpollServerTest, RunLine)
{
for(int i = 0; i <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; i++)
{
MyTcpServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) i);
TC_TCPClient client(LINE_HOST_EP.getHost(), LINE_HOST_EP.getPort(), LINE_HOST_EP.getTimeout());
int iRet = 0;
string sendBuffer(1024 * 1024 * 2, 'a');
string recvBuffer;
iRet = client.sendRecvLine((sendBuffer + "\r\n").c_str(), sendBuffer.size() + 2, recvBuffer);
ASSERT_TRUE(iRet == 0);
ASSERT_TRUE(recvBuffer == sendBuffer + "\r\n");
stopServer(server);
}
}
TEST_F(UtilEpollServerTest, AcceptCallback)
{
for(int i = 0; i <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; i++)
{
MyTcpServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE)i);
bool accept = false;
server._epollServer->setOnAccept([&](TC_EpollServer::Connection *conn)
{
accept = true;
});
TC_TCPClient client(TEST_HOST_EP.getHost(), TEST_HOST_EP.getPort(), TEST_HOST_EP.getTimeout());
int iRet = 0;
char recvBuffer[1024];
size_t recvLenth = 1024;
iRet = client.sendRecv("abc", 3, recvBuffer, recvLenth);
ASSERT_TRUE(iRet == 0);
ASSERT_TRUE(string(recvBuffer, recvLenth) == "abc");
TC_Common::msleep(50);
ASSERT_TRUE(accept);
stopServer(server);
}
}
TEST_F(UtilEpollServerTest, ConnectionMax)
{
for(int i = 0; i <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; i++)
{
MyTcpServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) i);
vector<TC_TCPClient *> conns;
//注意服务连接数是10个
for (int i = 0; i < 10; i++) {
TC_TCPClient
*client = new TC_TCPClient(TEST_HOST_EP.getHost(), TEST_HOST_EP.getPort(), TEST_HOST_EP.getTimeout());
int iRet = 0;
char recvBuffer[1024];
size_t recvLenth = 1024;
iRet = client->sendRecv("abc", 3, recvBuffer, recvLenth);
ASSERT_TRUE(iRet == 0);
ASSERT_TRUE(string(recvBuffer, recvLenth) == "abc");
conns.push_back(client);
}
TC_TCPClient client(TEST_HOST_EP.getHost(), TEST_HOST_EP.getPort(), TEST_HOST_EP.getTimeout());
int iRet = 0;
char recvBuffer[1024];
size_t recvLenth = 1024;
iRet = client.sendRecv("abc", 3, recvBuffer, recvLenth);
ASSERT_TRUE(iRet != 0);
for (size_t i = 0; i < conns.size(); i++) {
delete conns[i];
}
stopServer(server);
}
}
TEST_F(UtilEpollServerTest, QueueMode)
{
for(int i = 0; i <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; i++)
{
MyTcpServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) i);
vector<TC_TCPClient *> conns;
//注意服务连接数是10个
for (int i = 0; i < 10; i++) {
TC_TCPClient *client =
new TC_TCPClient(QUEUE_HOST_EP.getHost(), QUEUE_HOST_EP.getPort(), QUEUE_HOST_EP.getTimeout());
conns.push_back(client);
}
for (auto client : conns) {
string lastBuff;
for (int i = 0; i < 10; i++) {
int iRet = 0;
char recvBuffer[1024] = {0};
size_t recvLenth = 1024;
iRet = client->sendRecv("abc", 3, recvBuffer, recvLenth);
ASSERT_TRUE(iRet == 0);
if (!lastBuff.empty()) {
ASSERT_TRUE(lastBuff == string(recvBuffer, recvLenth));
}
lastBuff = string(recvBuffer, recvLenth);
}
}
for (size_t i = 0; i < conns.size(); i++) {
delete conns[i];
}
stopServer(server);
}
}

View File

@ -0,0 +1,129 @@
//
// Created by jarod on 2020/2/20.
//
#include "util/tc_file.h"
#include "gtest/gtest.h"
using namespace tars;
class UtilFileTest : public testing::Test
{
public:
//添加日志
static void SetUpTestCase()
{
// cout<<"SetUpTestCase"<<endl;
}
static void TearDownTestCase()
{
// cout<<"TearDownTestCase"<<endl;
}
virtual void SetUp() //TEST跑之前会执行SetUp
{
// cout<<"SetUp"<<endl;
}
virtual void TearDown() //TEST跑完之后会执行TearDown
{
// cout<<"TearDown"<<endl;
}
};
TEST_F(UtilFileTest, file) //此时使用的是TEST_F宏
{
string file = "./test.dat";
string data = "helloword";
data[3] = '\0';
TC_File::save2file(file, data);
size_t fileSize = TC_File::getFileSize(file);
// cout << "file size:" << fileSize << endl;
ASSERT_TRUE(fileSize == data.size());
string load = TC_File::load2str(file);
// cout << "load file size:" << load.size() << endl;
ASSERT_TRUE(load == data);
bool fileExists = TC_File::isFileExist(file, S_IFREG);
// cout << "file exists:" << fileExists << endl;
ASSERT_TRUE(fileExists);
string dir = "test";
TC_File::makeDir(dir);
fileExists = TC_File::isFileExist(dir, S_IFDIR);
// cout << "dir exists:" << fileExists << endl;
ASSERT_TRUE(fileExists);
string newFile = dir + FILE_SEP + file;
TC_File::save2file(newFile, data);
fileExists = TC_File::isFileExist(newFile, S_IFREG);
// cout << "newFile exists:" << fileExists << endl;
ASSERT_TRUE(fileExists);
TC_File::makeDir(dir + FILE_SEP + "test1");
TC_File::makeDir(dir + FILE_SEP + "test2");
vector<string> v;
TC_File::listDirectory(dir, v, true);
// cout << "listDirectory:" << endl;
// for(auto s : v)
// {
// cout << " " << s << endl;
// }
TC_File::removeFile(dir, true);
fileExists = TC_File::isFileExist(file, S_IFDIR);
// cout << "dir exists:" << fileExists << endl;
ASSERT_TRUE(!fileExists);
}
TEST_F(UtilFileTest, simplifyDirectory)
{
#if TARGET_PLATFORM_WINDOWS
// cout << "simplifyDirectory:" << TC_File::simplifyDirectory("/./ab/tt//t///t//../tt/") << endl;
ASSERT_TRUE(TC_File::simplifyDirectory("/./ab/tt//t///t//../tt/") == "ab\\tt\\t\\tt");
// cout << "simplifyDirectory:" << TC_File::simplifyDirectory("c:/ab/tt//t///t//../tt/") << endl;
ASSERT_TRUE(TC_File::simplifyDirectory("c:/ab/tt//t///t//../tt/") == "c:\\ab\\tt\\t\\tt");
#else
// cout << "simplifyDirectory:" << TC_File::simplifyDirectory("/./ab/tt//t///t//../tt/") << endl;
ASSERT_TRUE(TC_File::simplifyDirectory("/./ab/tt//t///t//../tt/") == "/ab/tt/t/tt");
// cout << "simplifyDirectory:" << TC_File::simplifyDirectory("/ab/tt//t///t//../tt/") << endl;
ASSERT_TRUE(TC_File::simplifyDirectory("/ab/tt//t///t//../tt/") == "/ab/tt/t/tt");
#endif
}
TEST_F(UtilFileTest, nameAndPath)
{
ASSERT_TRUE(TC_File::extractFileExt("/usr/local/app/bin.exe") == "exe");
ASSERT_TRUE(TC_File::extractFileExt("/usr/local/app/bin") == "");
ASSERT_TRUE(TC_File::extractFileExt("/usr/local/app.dir/bin.exe") == "exe");
ASSERT_TRUE(TC_File::extractFileExt("c:\\usr\\local\\app.dir\\bin.exe") == "exe");
ASSERT_TRUE(TC_File::extractFileExt("c:\\usr\\local\\app.dir\\bin") == "");
ASSERT_TRUE(TC_File::extractFileName("/usr/local/app/bin.exe") == "bin.exe");
ASSERT_TRUE(TC_File::extractFileName("/usr/local/app/bin") == "bin");
ASSERT_TRUE(TC_File::extractFileName("/usr/local/app.dir/bin.exe") == "bin.exe");
ASSERT_TRUE(TC_File::extractFileName("c:\\usr\\local\\app.dir\\bin.exe") == "bin.exe");
ASSERT_TRUE(TC_File::extractFileName("c:\\usr\\local\\app.dir\\bin") == "bin");
ASSERT_TRUE(TC_File::extractFileName("bin.exe") == "bin.exe");
ASSERT_TRUE(TC_File::extractFilePath("/usr/local/app/bin.exe") == "/usr/local/app/");
ASSERT_TRUE(TC_File::extractFilePath("/usr/local/app/bin") == "/usr/local/app/");
ASSERT_TRUE(TC_File::extractFilePath("/usr/local/app.dir/bin.exe") == "/usr/local/app.dir/");
ASSERT_TRUE(TC_File::extractFilePath("c:\\usr\\local\\app.dir\\bin.exe") == "c:\\usr\\local\\app.dir\\");
ASSERT_TRUE(TC_File::extractFilePath("c:\\usr\\local\\app.dir\\bin") == "c:\\usr\\local\\app.dir\\");
ASSERT_TRUE(TC_File::extractFilePath("temp.gif") == string(".") + FILE_SEP);
ASSERT_TRUE(TC_File::excludeFileExt("/usr/local/app/bin.exe") == "/usr/local/app/bin");
ASSERT_TRUE(TC_File::excludeFileExt("/usr/local/app/bin") == "/usr/local/app/bin");
ASSERT_TRUE(TC_File::excludeFileExt("/usr/local/app.dir/bin.exe") == "/usr/local/app.dir/bin");
ASSERT_TRUE(TC_File::excludeFileExt("c:\\usr\\local\\app.dir\\bin.exe") == "c:\\usr\\local\\app.dir\\bin");
ASSERT_TRUE(TC_File::excludeFileExt("c:\\usr\\local\\app.dir\\bin") == "c:\\usr\\local\\app.dir\\bin");
ASSERT_TRUE(TC_File::excludeFileExt("temp.gif") == "temp");
}

View File

@ -0,0 +1,868 @@
//
// Created by jarod on 2020/2/20.
//
#include "util/tc_http.h"
#include "util/tc_common.h"
#include "util/tc_file.h"
#include "util/tc_http_async.h"
#include "gtest/gtest.h"
using namespace tars;
class UtilHttpTest : public testing::Test
{
public:
//添加日志
static void SetUpTestCase()
{
// cout<<"SetUpTestCase"<<endl;
}
static void TearDownTestCase()
{
// cout<<"TearDownTestCase"<<endl;
}
virtual void SetUp() //TEST跑之前会执行SetUp
{
// cout<<"SetUp"<<endl;
}
virtual void TearDown() //TEST跑完之后会执行TearDown
{
// cout<<"TearDown"<<endl;
}
};
TEST_F(UtilHttpTest, testCheckRequestURL) //此时使用的是TEST_F宏
{
string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n")
+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+string("Accept-Encoding: gzip\r\n")
+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+string("Connection: close\r\n")
+string("Host: www.qq.com\r\n")
+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
TC_HttpRequest req;
ASSERT_TRUE(req.decode(s));
ASSERT_TRUE(req.getRequestUrl() == "/a/b");
ASSERT_TRUE(req.getURL().getDomain() == "www.qq.com");
}
TEST_F(UtilHttpTest, testHttp) //此时使用的是TEST_F宏
{
TC_HttpRequest stHttpReq;
stHttpReq.setCacheControl("no-cache");
stHttpReq.setGetRequest("http://www.qq.com/", true);
TC_HttpResponse stHttpRsp;
int ret = stHttpReq.doRequest(stHttpRsp, 3000);
ASSERT_TRUE(ret == 0);
// cout << ret << ":" << stHttpRsp.getContent() << endl;
// cout << "\n\n==============================\n" << stHttpRsp.getContent().size() << endl;
// cout << stHttpRsp.genHeader() << endl;
}
TEST_F(UtilHttpTest, testEncodeString) //此时使用的是TEST_F宏
{
string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n")
+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+string("Accept-Encoding: gzip\r\n")
+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+string("Connection: close\r\n")
+string("Host: www.qq.com\r\n")
+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
// s += string("a", 1024);
TC_HttpRequest req;
req.decode(s);
int64_t t = TC_Common::now2us();
int count = 100000;
int i = 0;
while(++i<count) {
string s;
s = req.encode();
}
ASSERT_TRUE(req.decode(s));
ASSERT_TRUE(req.getRequestUrl() == "/a/b");
ASSERT_TRUE(req.getURL().getDomain() == "www.qq.com");
cout << "testEncodeString::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl;
}
TEST_F(UtilHttpTest, testEncodeVector) //此时使用的是TEST_F宏
{
string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n")
+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+string("Accept-Encoding: gzip\r\n")
+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+string("Connection: close\r\n")
+string("Host: www.qq.com\r\n")
+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
s += string("a", 1024);
TC_HttpRequest req;
req.decode(s);
int64_t t = TC_Common::now2us();
int count = 100000;
int i = 0;
while(++i<count) {
vector<char> buff;
req.encode(buff);
}
cout << "testEncodeVector::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl;
}
TEST_F(UtilHttpTest, testEncodeBuffString) //此时使用的是TEST_F宏
{
string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\\r\n")
+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+string("Accept-Encoding: gzip\r\n")
+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+string("Connection: close\r\n")
+string("Host: www.qq.com\r\n")
+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
int64_t t = TC_Common::now2us();
TC_HttpRequest req;
req.decode(s);
TC_NetWorkBuffer buff(NULL);
int count = 100000;
int i = 0;
while(++i<count) {
req.encode(buff);
}
cout << "testEncodeBuffString::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl;
}
TEST_F(UtilHttpTest, testDecodeString) //此时使用的是TEST_F宏
{
string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n")
+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+string("Accept-Encoding: gzip\r\n")
+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+string("Connection: close\r\n")
+string("Host: www.qq.com\r\n")
+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
int64_t t = TC_Common::now2us();
int count = 100000;
int i = 0;
while(++i<count) {
TC_HttpRequest req;
req.decode(s);
}
cout << "testDecodeString::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl;
}
TEST_F(UtilHttpTest, testDecodeBuffString) //此时使用的是TEST_F宏
{
string s = string("HTTP/1.1 200 OK\r\n")
+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+string("Accept-Encoding: gzip\r\n")
+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+string("Connection: close\r\n")
+string("Host: www.qq.com\r\n")
+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
int count = 100000;
int i = 0;
vector<TC_NetWorkBuffer> vbuff;
while(i<count) {
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s);
vbuff.push_back(buff);
++i;
}
int64_t t = TC_Common::now2us();
i = 0;
while(i<count) {
TC_HttpResponse req;
ASSERT_FALSE(req.incrementDecode(vbuff[i]));
++i;
}
cout << "testDecodeBuffString::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl;
}
TEST_F(UtilHttpTest, testCheckRequestString) //此时使用的是TEST_F宏
{
string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n")
+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+string("Accept-Encoding: gzip\r\n")
+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+string("Connection: close\r\n")
+string("Host: www.qq.com\r\n")
+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
int64_t t = TC_Common::now2us();
TC_HttpRequest req;
int count = 100000;
int i = 0;
while(++i<count) {
ASSERT_TRUE(req.checkRequest(s.c_str(), s.size()));
}
ASSERT_TRUE(req.decode(s));
ASSERT_TRUE(req.getRequestUrl() == "/a/b");
cout << req.getURL().getDomain() << endl;
ASSERT_TRUE(req.getURL().getDomain() == "www.qq.com");
cout << "testCheckRequestString::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl;
}
TEST_F(UtilHttpTest, testCheckRequestBuff) //此时使用的是TEST_F宏
{
string s = string("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n")
+string("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n")
+string("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n")
+string("Accept-Encoding: gzip\r\n")
+string("Accept-Language: zh-cn,zh;q=0.5\r\n")
+string("Connection: close\r\n")
+string("Host: www.qq.com\r\n")
+string("Q-GUID: 08f0373a192a45778cc8567d1c641475\r\n")
+string("Q-UA: SQB12_GA/120450&SMTT_3/020100&SYM3&201514&E71&V2\r\n")
+string("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
int64_t t = TC_Common::now2us();
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s.c_str(), s.size());
TC_HttpRequest req;
int count = 100000;
int i = 0;
while(++i<count) {
ASSERT_TRUE(req.checkRequest(buff));
}
cout << "testCheckRequestBuff::cost: " << TC_Common::now2us() - t << "us, " << 1.*(TC_Common::now2us() - t)/count << "us" << endl;
}
TEST_F(UtilHttpTest, testHttpFinish) //此时使用的是TEST_F宏
{
string body = "abdefghigk";
vector<string> sbuff;
sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n");
sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
sbuff.push_back("Accept-Encoding: gzip\r\n");
sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size()) + "\r\n");
sbuff.push_back("Connection: close\r\n");
sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
string header;
for(auto s : sbuff)
{
header += s;
}
string s = header + body;
TC_HttpRequest request;
ASSERT_TRUE(request.checkRequest(s.c_str(), s.size()));
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s.c_str(), s.size());
ASSERT_TRUE(buff.checkHttp() == TC_NetWorkBuffer::PACKET_FULL);
}
TEST_F(UtilHttpTest, testHttpFinishNoLength) //此时使用的是TEST_F宏
{
vector<string> sbuff;
sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n");
sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
sbuff.push_back("Accept-Encoding: gzip\r\n");
sbuff.push_back("Connection: close\r\n");
sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
string header;
for(auto s : sbuff)
{
header += s;
}
string s = header;
TC_HttpRequest request;
ASSERT_TRUE(request.checkRequest(s.c_str(), s.size()));
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s.c_str(), s.size());
ASSERT_TRUE(buff.checkHttp() == TC_NetWorkBuffer::PACKET_FULL);
}
TEST_F(UtilHttpTest, testHttpNoFinish) //此时使用的是TEST_F宏
{
string body = "abdefghigk";
vector<string> sbuff;
sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n");
sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
sbuff.push_back("Accept-Encoding: gzip\r\n");
sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size() + 1) + "\r\n");
sbuff.push_back("Connection: close\r\n");
sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
string header;
for(auto s : sbuff)
{
header += s;
}
string s = header + body;
TC_HttpRequest request;
ASSERT_TRUE(!request.checkRequest(s.c_str(), s.size()));
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s.c_str(), s.size());
ASSERT_TRUE(buff.checkHttp() == TC_NetWorkBuffer::PACKET_LESS);
}
TEST_F(UtilHttpTest, testHttpRequestChunked) //此时使用的是TEST_F宏
{
vector<string> body;
body.push_back("abasdfadefghiadfagk1");
body.push_back("abdasdfadfaefghigk2");
body.push_back("abdsaefghigk3");
body.push_back("abdeasdfafasfasfasfasdfasffghigk4");
vector<string> sbuff;
sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n");
sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
sbuff.push_back("Accept-Encoding: gzip\r\n");
sbuff.push_back("Transfer-Encoding: chunked\r\n");
sbuff.push_back("Connection: close\r\n");
sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
stringstream data;
for(auto s : sbuff)
{
data << s;
}
string sbody;
for(auto s : body)
{
sbody += s;
data << hex << s.size() << "\r\n" << s << "\r\n";
}
data << 0 << "\r\n\r\n";
string s = data.str();
TC_HttpRequest request;
ASSERT_TRUE(request.checkRequest(s.c_str(), s.size()));
ASSERT_TRUE(request.decode(s));
ASSERT_TRUE(request.getContent() == sbody);
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s.c_str(), s.size());
request.reset();
ASSERT_TRUE(request.checkRequest(buff));
}
TEST_F(UtilHttpTest, testHttpRequestChunkedNoFinish) //此时使用的是TEST_F宏
{
vector<string> body;
body.push_back("abasdfadefghiadfagk1");
body.push_back("abdasdfadfaefghigk2");
body.push_back("abdsaefghigk3");
body.push_back("abdeasdfafasfasfasfasdfasffghigk4");
vector<string> sbuff;
sbuff.push_back("GET /a/b?name=value&ccc=ddd HTTP/1.1\r\n");
sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
sbuff.push_back("Accept-Encoding: gzip\r\n");
sbuff.push_back("Transfer-Encoding: chunked\r\n");
sbuff.push_back("Connection: close\r\n");
sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
stringstream data;
for(auto s : sbuff)
{
data << s;
}
data << hex << body[0].size() << "\r\n" << body[0] << "\r\n";
data << hex << body[1].size() << "\r\n" << body[1] << "\r\n";
data << hex << body[2].size() ;
string s = data.str();
TC_HttpRequest request;
ASSERT_TRUE(!request.checkRequest(s.c_str(), s.size()));
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s.c_str(), s.size());
ASSERT_TRUE(!request.checkRequest(buff));
}
TEST_F(UtilHttpTest, testHttpResponse) //此时使用的是TEST_F宏
{
string body = "abcdef";
vector<string> sbuff;
sbuff.push_back("HTTP/1.1 200 OK\r\n");
sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size()) + "\r\n");
sbuff.push_back("\r\n");
string header;
for(auto s : sbuff)
{
header += s;
}
string s = header + body;
{
TC_HttpResponse response;
ASSERT_TRUE(response.decode(s));
ASSERT_TRUE(response.getContent() == body);
}
{
TC_HttpResponse response;
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s.c_str(), s.size());
ASSERT_TRUE(response.incrementDecode(buff));
ASSERT_TRUE(response.getContent() == body);
}
}
TEST_F(UtilHttpTest, testHttpResponseNoFinish) //此时使用的是TEST_F宏
{
string body = "abcdef";
vector<string> sbuff;
sbuff.push_back("HTTP/1.1 200 OK\r\n");
sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size() + 1) + "\r\n");
sbuff.push_back("\r\n");
string header;
for(auto s : sbuff)
{
header += s;
}
string s = header + body;
{
TC_HttpResponse response;
ASSERT_TRUE(!response.decode(s));
}
{
TC_HttpResponse response;
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s.c_str(), s.size());
ASSERT_TRUE(!response.incrementDecode(buff));
}
}
TEST_F(UtilHttpTest, testHttpResponseNoLength) //此时使用的是TEST_F宏
{
vector<string> sbuff;
sbuff.push_back("HTTP/1.1 200 OK\r\n");
sbuff.push_back("Connection: close\r\n");
sbuff.push_back("\r\n");
string header;
for(auto s : sbuff)
{
header += s;
}
string s = header;
{
TC_HttpResponse response;
ASSERT_TRUE(response.decode(s));
}
{
TC_HttpResponse response;
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s.c_str(), s.size());
ASSERT_FALSE(response.incrementDecode(buff));
}
}
TEST_F(UtilHttpTest, testHttpResponseIncrementFinish) //此时使用的是TEST_F宏
{
string body = "abcdeasdfadfsff";
vector<string> sbuff;
sbuff.push_back("HTTP/1.1 200 OK\r\n");
sbuff.push_back("Content-Length: " + TC_Common::tostr(body.size()) + "\r\n");
sbuff.push_back("\r\n");
string header;
for(auto s : sbuff)
{
header += s;
}
string s = header;
{
TC_HttpResponse response;
ASSERT_TRUE(!response.decode(s));
}
{
TC_HttpResponse response;
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s.c_str(), s.size());
ASSERT_TRUE(!response.incrementDecode(buff));
}
s = header + body;
{
TC_HttpResponse response;
ASSERT_TRUE(response.decode(s));
}
{
TC_HttpResponse response;
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s.c_str(), s.size());
ASSERT_TRUE(response.incrementDecode(buff));
}
}
TEST_F(UtilHttpTest, testHttpResponseChunked) //此时使用的是TEST_F宏
{
vector<string> body;
body.push_back("abdefghiasdfasdfsadfsadfsagk1");
body.push_back("abdefghasdfaaigk2");
body.push_back("abdefghigadsfadsfk3");
body.push_back("abdefgsfagasasdfasfdfdfsdfsfsdfdsffsdfsdfhigk4");
vector<string> sbuff;
sbuff.push_back("HTTP/1.1 200 OK\r\n");
sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
sbuff.push_back("Transfer-Encoding: chunked\r\n");
sbuff.push_back("Connection: close\r\n\r\n");
stringstream data;
for(auto s : sbuff)
{
data << s;
}
string sbody;
for(auto s : body)
{
sbody += s;
data << hex << s.size() << "\r\n" << s << "\r\n";
}
data << 0 << "\r\n\r\n";
string s = data.str();
{
TC_HttpResponse response;
ASSERT_TRUE(response.decode(s));
ASSERT_TRUE(response.getContent() == sbody);
}
{
TC_HttpResponse response;
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s.c_str(), s.size());
ASSERT_TRUE(response.incrementDecode(buff));
ASSERT_TRUE(response.getContent() == sbody);
}
}
TEST_F(UtilHttpTest, testHttpResponseChunkedNoFinish) //此时使用的是TEST_F宏
{
vector<string> body;
body.push_back("abdefasdfasfasghigk1");
body.push_back("asdfaabdeafghigk2");
body.push_back("abasdfasdfasdfasdfasdfasdfasfasdefghigk3");
body.push_back("abdefgfasdfasdfasdfasdfadfigk4");
vector<string> sbuff;
sbuff.push_back("HTTP/1.1 200 OK\r\n");
sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
sbuff.push_back("Transfer-Encoding: chunked\r\n");
sbuff.push_back("Connection: close\r\n\r\n");
stringstream data;
for(auto s : sbuff)
{
data << s;
}
data << hex << body[0].size() << "\r\n" << body[0] << "\r\n";
data << hex << body[1].size() << "\r\n" << body[1] << "\r\n";
data << hex << body[2].size() << "\r\n" << "abc";
string s = data.str();
{
TC_HttpResponse response;
ASSERT_TRUE(!response.decode(s));
}
{
TC_HttpResponse response;
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s.c_str(), s.size());
ASSERT_TRUE(!response.incrementDecode(buff));
}
}
void testCookie(const string &sRspURL, const string &sReqURL, const vector<string> &vsCookie)
{
// cout << sRspURL << "=>" << sReqURL << "-----------------------------------" << endl;
TC_HttpCookie cookie;
cookie.addCookie(sRspURL, vsCookie);
// list<TC_HttpCookie::Cookie> vCookie = cookie.getAllCookie();
// list<TC_HttpCookie::Cookie>::iterator it = vCookie.begin();
// while(it != vCookie.end())
// {
// cout << TC_Common::tostr(it->_data.begin(), it->_data.end(), "; ") << ", " << it->_expires << ", " << it->_path << endl;
// ++it;
// }
// cout << "-----------------------------------" << endl << endl;
string sCookie;
cookie.getCookieForURL(sReqURL, sCookie);
// cout << TC_Common::tostr(sCookie) << endl;
// cout << "-----------------------------------" << endl << endl;
}
TEST_F(UtilHttpTest, testCookie) //此时使用的是TEST_F宏
{
ASSERT_TRUE(TC_HttpCookie::matchDomain("qq.com", "www.qq.com") == true);
ASSERT_TRUE(TC_HttpCookie::matchDomain(".qq.com", "www.qq.com") == true);
ASSERT_TRUE(TC_HttpCookie::matchDomain(".qq.com", "qq.com") == true);
ASSERT_TRUE(TC_HttpCookie::matchDomain("t.qq.com", "www.qq.com") == false);
ASSERT_TRUE(TC_HttpCookie::matchDomain(".t.qq.com", "www.qq.com") == false);
ASSERT_TRUE(TC_HttpCookie::matchDomain(".t.qq.com", "t.qq.com") == true);
ASSERT_TRUE(TC_HttpCookie::matchDomain(".com", "www.qq.com") == false);
ASSERT_TRUE(TC_HttpCookie::matchDomain(".com", "qq.com") == false);
ASSERT_TRUE(TC_HttpCookie::matchDomain(".y.qq.com", "x.y.qq.com") == true);
ASSERT_TRUE(TC_HttpCookie::matchDomain(".x.y.qq.com", "x.y.qq.com") == true);
ASSERT_TRUE(TC_HttpCookie::matchDomain(".qq.com", "x.y.qq.com") == true);
ASSERT_TRUE(TC_HttpCookie::matchDomain(".qq.com", "y.qq.com") == true);
ASSERT_TRUE(TC_HttpCookie::matchDomain("qq.com", "y.qq.com") == true);
// cout << TC_Common::now2GMTstr() << endl;
string gmt = TC_Common::tm2GMTstr(time(NULL) + 10);
string s = "HTTP/1.1 200 OK\r\n";// 200 Aouut Error\r\n";
s += "Set-Cookie: n1=1; a=1; c=d; Path=/; Domain=qq.com; Expires=" + gmt + "\r\n";
s += "Set-Cookie: n2=2; a=0; c=d; Path=/abc/def; Domain=.qq.com; Expires=" + gmt + "\r\n";
s += "Set-Cookie: n3=3; a=5; c=d; Path=/abc/def/aaa; Domain=.qq.com; Expires=" + gmt + "\r\n";
s += "Set-Cookie: n4=4; a=6; c=d; Path=/abc; Domain=.qq.com; Expires=" + gmt + "\r\n";
s += "Set-Cookie: n5=5; a=2; c=d; Path=/; Domain=.qq.com; Expires=" + gmt + "\r\n";
s += "Set-Cookie: n6=6; c=3; Path=/; Domain=y.qq.com; Expires=" + gmt + "\r\n";
s += "Set-Cookie: n7=7; c=3; Path=/abc; Domain=.y.qq.com; Expires=" + gmt + "\r\n";
s += "Set-Cookie: n8=6; c=3; Path=/; Domain=x.y.qq.com; Expires=" + gmt + "\r\n";
s += "Set-Cookie: n9=7; c=4; Path=/; Domain=.x.y.qq.com; Expires=" + gmt + "\r\n";
s += "Set-Cookie: n10=7; c=4; Path=/; Domain=qqq.com; Expires=" + gmt + "\r\n";
s += "Set-Cookie: n11=7; c=4; Path=/; Domain=.qqq.com; Expires=" + gmt + "\r\n";
s += "Set-Cookie: n12=8; c=4; Expires=" + gmt + "\r\n";
s += "Accept-Ranges: bytes\r\n\r\n";
TC_HttpResponse rsp;
rsp.decode(s);
// cout << "-----------------------------------" << endl;
vector<string> vsCookie = rsp.getSetCookie();
// cout << TC_Common::tostr(vsCookie.begin(), vsCookie.end(), "\r\n") << endl << endl;
testCookie("http://www.qq.com", "http://www.qq.com", vsCookie);
testCookie("http://www.qq.com/abc/def", "http://www.qq.com", vsCookie);
testCookie("http://www.qq.com/abc/def", "http://www.qq.com/abc", vsCookie);
// cout << endl;
testCookie("http://www.qq.com", "http://qq.com", vsCookie);
testCookie("http://www.qq.com/abc/def/aaa", "http://www.qq.com/abc/def/aaa", vsCookie);
testCookie("http://www.qq.com/abc/def/aaa", "http://www.qq.com", vsCookie);
testCookie("http://www.qq.com", "http://www.qq.com/abc/def", vsCookie);
testCookie("http://qq.com", "http://qq.com/abc/def", vsCookie);
testCookie("http://qq.com", "http://t.qq.com/abc/def", vsCookie);
testCookie("http://qq.com", "http://y.qq.com/", vsCookie);
testCookie("http://qq.com", "http://y.qq.com/abc", vsCookie);
testCookie("http://x.y.qq.com", "http://x.y.qq.com", vsCookie);
}
TEST_F(UtilHttpTest, testQQ) //此时使用的是TEST_F宏
{
string url = "www.qq.com";
TC_HttpRequest stHttpReq;
// stHttpReq.setCacheControl("no-cache");
// stHttpReq.setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36");
stHttpReq.setUserAgent("E71/SymbianOS/9.1 Series60/3.0");
stHttpReq.setHeader("Connection", "Close");
stHttpReq.setAcceptEncoding("gzip, deflate, br");
stHttpReq.setGetRequest(url);
string sSendBuffer = stHttpReq.encode();
TC_HttpResponse stHttpRsp;
int iRet = stHttpReq.doRequest(stHttpRsp, 5000);
ASSERT_TRUE(iRet == 0);
ASSERT_TRUE(stHttpRsp.hasHeader("Location"));
}
TEST_F(UtilHttpTest, testBaidu) //此时使用的是TEST_F宏
{
string url = "www.baidu.com";
TC_HttpRequest stHttpReq;
stHttpReq.setUserAgent("E71/SymbianOS/9.1 Series60/3.0");
stHttpReq.setHeader("Connection", "Close");
stHttpReq.setAcceptEncoding("gzip, deflate, br");
stHttpReq.setGetRequest(url);
string sSendBuffer = stHttpReq.encode();
TC_HttpResponse stHttpRsp;
int iRet = stHttpReq.doRequest(stHttpRsp, 5000);
ASSERT_TRUE(iRet == 0);
//
// string file = stHttpReq.getURL().getDomain() + ".html";
//
// auto headers = stHttpRsp.getHeaders();
//
// cout << "request:" << url << endl;
// cout << TC_Common::tostr(headers.begin(), headers.end(), "\r\n") << endl;
// TC_File::save2file(file, stHttpRsp.getContent());
ASSERT_TRUE(stHttpRsp.getContentLength() == stHttpRsp.getContent().length());
}
TEST_F(UtilHttpTest, testIncrementDecode1)
{
TC_HttpResponse rsp;
string data = "ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd-0-139896025024448";
string s = "HTTP/1.1 200 OK\r\n";
s += "Content-Length : 115\r\n\r\n";
s += data;
TC_NetWorkBuffer::Buffer buff;
buff.addBuffer(s);
bool flag = rsp.incrementDecode(buff);
// LOG_CONSOLE_DEBUG << rsp.getContent() << endl;
ASSERT_TRUE(flag);
ASSERT_TRUE(rsp.getContent() == data);
}
TEST_F(UtilHttpTest, testIncrementDecode2)
{
TC_HttpResponse rsp;
string data = "ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd-0-139896025024448";
string s = "HTTP/1.1 200 OK\r\n";
s += "Content-Length : 115\r\n\r\n";
s += data;
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s);
bool flag = rsp.incrementDecode(buff);
// LOG_CONSOLE_DEBUG << rsp.getContent() << endl;
ASSERT_TRUE(flag);
ASSERT_TRUE(rsp.getContent() == data);
}

View File

@ -0,0 +1,419 @@
//
// Created by jarod on 2020/2/20.
//
#include "util/tc_http.h"
#include "util/tc_common.h"
#include "util/tc_http_async.h"
#include "util/tc_md5.h"
#include "test_server.h"
#include "gtest/gtest.h"
#include "certs.h"
using namespace tars;
class UtilHttpAsyncTest : public testing::Test
{
public:
//添加日志
static void SetUpTestCase()
{
}
static void TearDownTestCase()
{
}
virtual void SetUp() //TEST跑之前会执行SetUp
{
}
virtual void TearDown() //TEST跑完之后会执行TearDown
{
}
void startServer(MyHttpServer &server, TC_EpollServer::SERVER_OPEN_COROUTINE openCoroutine)
{
#if TARGET_PLATFORM_LINUX || TARGET_PLATFORM_IOS
TC_Common::ignorePipe();
#endif
server.initialize();
server._epollServer->setOpenCoroutine(openCoroutine);
server.bindHttp("tcp -h 0.0.0.0 -p 18077 -t 60000");
#if TARS_SSL
server.bindHttpSSL("ssl -h 0.0.0.0 -p 18080 -t 60000");
server.bindHttpSSLVerify("ssl -h 0.0.0.0 -p 18180 -t 60000");
#endif
server.waitForShutdown();
}
void stopServer(MyHttpServer &server)
{
server.terminate();
}
};
class AsyncHttpCallback : public TC_HttpAsync::RequestCallback
{
public:
AsyncHttpCallback(const string &sUrl) : _sUrl(sUrl)
{
}
virtual bool onContinue(TC_HttpResponse &stHttpResponse) { return true; }
virtual void onSucc(TC_HttpResponse &stHttpResponse)
{
_rsp = stHttpResponse;
}
virtual void onFailed(FAILED_CODE ret, const string &info)
{
LOG_CONSOLE_DEBUG << "onFailed, code:" << ret << ", info:" << info << "," << _sUrl << endl;
}
virtual void onClose()
{
// LOG_CONSOLE_DEBUG << "onClose:" << _sUrl << endl;
}
public:
string _sUrl;
TC_HttpResponse _rsp;
};
class DownloadCallback : public TC_HttpAsync::RequestCallback
{
public:
DownloadCallback()
: _fp(NULL)
{
}
virtual void onSucc(TC_HttpResponse &stHttpResponse)
{
if (_fp)
{
fclose(_fp);
_fp = NULL;
}
_md5 = TC_MD5::md5file("winrar");
// LOG_CONSOLE_DEBUG << "onSucc:" << TC_File::getFileSize("winrar") << endl;
};
virtual bool onContinue(TC_HttpResponse &stHttpResponse)
{
// LOG_CONSOLE_DEBUG << "recv length:" << stHttpResponse.getContent().length() << endl;
if (_fp == NULL)
{
string file = "winrar";
_fp = fopen(file.c_str(), "wb");
}
string content = stHttpResponse.getContent();
fwrite(content.c_str(), 1, content.length(), _fp);
stHttpResponse.clearContent();
return true;
}
virtual void onFailed(FAILED_CODE ret, const string &info) {
// cout << "onFailed:" << ret << ", " << info << endl;
};
virtual void onClose()
{
if (_fp)
{
fclose(_fp);
_fp = NULL;
}
}
string _md5;
FILE *_fp;
};
TEST_F(UtilHttpAsyncTest, testSync)
{
int type = 2;
for(type = 0; type <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; type++)
{
MyHttpServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) type);
int i = 100;
while (i-- > 0)
{
string url = "http://127.0.0.1:18077";
TC_HttpRequest stHttpReq;
stHttpReq.setUserAgent("E71/SymbianOS/9.1 Series60/3.0");
stHttpReq.setHeader("Connection", "Close");
stHttpReq.setAcceptEncoding("gzip, deflate, br");
stHttpReq.setPostRequest(url, "test info");
string sSendBuffer = stHttpReq.encode();
// LOG_CONSOLE_DEBUG << sSendBuffer << endl;
TC_HttpResponse stHttpRsp;
int iRet = stHttpReq.doRequest(stHttpRsp, 5000);
ASSERT_TRUE(iRet == 0);
ASSERT_TRUE(stHttpRsp.getContent() == stHttpReq.getContent());
}
stopServer(server);
}
}
TEST_F(UtilHttpAsyncTest, testAsync)
{
int type = 2;
for(type = 0; type <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; type++)
{
MyHttpServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) type);
string url = "http://127.0.0.1:18077";
TC_HttpRequest stHttpReq;
stHttpReq.setUserAgent("E71/SymbianOS/9.1 Series60/3.0");
stHttpReq.setHeader("Connection", "Close");
stHttpReq.setAcceptEncoding("gzip, deflate, br");
stHttpReq.setPostRequest(url, string("test info"), true);
TC_HttpAsync ast;
ast.setTimeout(10000);
ast.start();
int i = 100;
while (i-- > 0)
{
AsyncHttpCallback *callback = new AsyncHttpCallback(url);
TC_HttpAsync::RequestCallbackPtr p(callback);
ast.doAsyncRequest(stHttpReq, p);
TC_Common::msleep(50);
ASSERT_TRUE(callback->_rsp.getContent() == stHttpReq.getContent());
}
ast.waitForAllDone();
stopServer(server);
}
}
TEST_F(UtilHttpAsyncTest, testDownload)
{
int type = 2;
for(type = 0; type <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; type++) {
MyHttpServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) type);
TC_HttpAsync ast;
ast.setTimeout(10000);
ast.start();
string url = "http://cdn.tarsyun.com/src/release-1.10.0.tar.gz";
TC_HttpRequest stHttpReq;
stHttpReq.setGetRequest(url);
DownloadCallback *callback = new DownloadCallback();
TC_HttpAsync::RequestCallbackPtr p(callback);
ast.doAsyncRequest(stHttpReq, p);
ast.waitForAllDone();
ASSERT_TRUE(callback->_md5 == "ecd1fa65e7de707cd5c00bdac56022cd");
stopServer(server);
}
}
#if TARS_SSL
TEST_F(UtilHttpAsyncTest, testAsyncSSL)
{
int type = 2;
for(type = 0; type <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; type++)
{
MyHttpServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) type);
string url = "https://127.0.0.1:18080";
TC_HttpRequest stHttpReq;
stHttpReq.setUserAgent("E71/SymbianOS/9.1 Series60/3.0");
stHttpReq.setHeader("Connection", "Close");
stHttpReq.setAcceptEncoding("gzip, deflate, br");
stHttpReq.setPostRequest(url, string("test info"), true);
TC_HttpAsync ast;
ast.setTimeout(10000);
ast.start();
int i = 100;
while (i-- > 0)
{
AsyncHttpCallback *callback = new AsyncHttpCallback(url);
TC_HttpAsync::RequestCallbackPtr p(callback);
ast.doAsyncRequest(stHttpReq, p);
TC_Common::msleep(50);
ASSERT_TRUE(callback->_rsp.getContent() == stHttpReq.getContent());
}
ast.waitForAllDone();
stopServer(server);
}
}
TEST_F(UtilHttpAsyncTest, testAsyncSSLCtxVerify)
{
string ciphers = "";
bool verifyClient = true;
shared_ptr<TC_OpenSSL::CTX> ctx = TC_OpenSSL::newCtx(SERVER_CERT, CLIENT_CERT, CLIENT_KEY, verifyClient, ciphers);
int type = 2;
for(type = 0; type <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; type++)
{
MyHttpServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) type);
string url = "https://127.0.0.1:18180";
TC_HttpRequest stHttpReq;
stHttpReq.setUserAgent("E71/SymbianOS/9.1 Series60/3.0");
stHttpReq.setHeader("Connection", "Close");
stHttpReq.setAcceptEncoding("gzip, deflate, br");
stHttpReq.setPostRequest(url, string("test info"), true);
TC_HttpAsync ast;
ast.setCtx(ctx);
ast.setTimeout(10000);
ast.start();
int i = 100;
while (i-- > 0)
{
AsyncHttpCallback *callback = new AsyncHttpCallback(url);
TC_HttpAsync::RequestCallbackPtr p(callback);
ast.doAsyncRequest(stHttpReq, p);
TC_Common::msleep(50);
ASSERT_TRUE(callback->_rsp.getContent() == stHttpReq.getContent());
}
ast.waitForAllDone();
stopServer(server);
}
}
TEST_F(UtilHttpAsyncTest, testAsyncSSLCtx)
{
bool verifyClient = false;
string ciphers = "";
shared_ptr<TC_OpenSSL::CTX> ctx = TC_OpenSSL::newCtx(SERVER_CERT, "", "", verifyClient, ciphers);
int type = 2;
for(type = 0; type <= TC_EpollServer::NET_THREAD_MERGE_HANDLES_CO; type++)
{
MyHttpServer server;
startServer(server, (TC_EpollServer::SERVER_OPEN_COROUTINE) type);
string url = "https://127.0.0.1:18080";
TC_HttpRequest stHttpReq;
stHttpReq.setUserAgent("E71/SymbianOS/9.1 Series60/3.0");
stHttpReq.setHeader("Connection", "Close");
stHttpReq.setAcceptEncoding("gzip, deflate, br");
stHttpReq.setPostRequest(url, string("test info"), true);
TC_HttpAsync ast;
ast.setCtx(ctx);
ast.setTimeout(10000);
ast.start();
int i = 100;
while (i-- > 0)
{
AsyncHttpCallback *callback = new AsyncHttpCallback(url);
TC_HttpAsync::RequestCallbackPtr p(callback);
ast.doAsyncRequest(stHttpReq, p);
TC_Common::msleep(50);
ASSERT_TRUE(callback->_rsp.getContent() == stHttpReq.getContent());
}
ast.waitForAllDone();
stopServer(server);
}
}
TEST_F(UtilHttpAsyncTest, testRemoteAsyncSSL)
{
string url = "https://www.qq.com";
TC_HttpRequest stHttpReq;
stHttpReq.setUserAgent("E71/SymbianOS/9.1 Series60/3.0");
stHttpReq.setHeader("Connection", "Close");
stHttpReq.setAcceptEncoding("gzip, deflate, br");
stHttpReq.setGetRequest(url);
TC_HttpAsync ast;
ast.setTimeout(10000);
ast.start();
int i = 100;
while (i-- > 0)
{
AsyncHttpCallback *callback = new AsyncHttpCallback(url);
TC_HttpAsync::RequestCallbackPtr p(callback);
ast.doAsyncRequest(stHttpReq, p);
TC_Common::msleep(50);
ASSERT_TRUE(callback->_rsp.getStatus() == 200);
}
ast.waitForAllDone();
}
#endif

View File

@ -0,0 +1,56 @@
//
// Created by jarod on 2021/8/09.
//
#include "util/tc_json.h"
#include "gtest/gtest.h"
using namespace tars;
class UtilTest : public testing::Test
{
public:
//添加日志
static void SetUpTestCase()
{
// cout<<"SetUpTestCase"<<endl;
}
static void TearDownTestCase()
{
// cout<<"TearDownTestCase"<<endl;
}
virtual void SetUp() //TEST跑之前会执行SetUp
{
// cout<<"SetUp"<<endl;
}
virtual void TearDown() //TEST跑完之后会执行TearDown
{
// cout<<"TearDown"<<endl;
}
};
TEST_F(UtilTest, json)
{
int64_t point = 0x100000000000001;
// cout << "point=" << point << endl;
// double x = point;
// int64_t point2 = x;
// cout << "point=" << point2 << endl;
// cout << std::to_string(x) << endl;
string buff = "{ \"x\": 72057594037927937}";
auto d = JsonValueObjPtr::dynamicCast(TC_Json::getValue(buff));
auto v = JsonValueNumPtr ::dynamicCast(d->get("x"));
// cout << v->isInt << ", " << v->lvalue << ", " << (int64_t)v->value << endl;
ASSERT_TRUE(v->isInt);
ASSERT_TRUE(v->lvalue == point);
//double精度有问题!!!
ASSERT_TRUE((int64_t)v->value != point);
}

View File

@ -0,0 +1,453 @@
//
// Created by jarod on 2020/2/20.
//
#include "util/tc_network_buffer.h"
#include "util/tc_logger.h"
#include "gtest/gtest.h"
using namespace tars;
class UtilNetworkBufferTest : public testing::Test
{
public:
//添加日志
static void SetUpTestCase()
{
// cout<<"SetUpTestCase"<<endl;
}
static void TearDownTestCase()
{
// cout<<"TearDownTestCase"<<endl;
}
virtual void SetUp() //TEST跑之前会执行SetUp
{
// cout<<"SetUp"<<endl;
}
virtual void TearDown() //TEST跑完之后会执行TearDown
{
// cout<<"TearDown"<<endl;
}
};
TEST_F(UtilNetworkBufferTest, testBuffer1) //此时使用的是TEST_F宏
{
uint32_t a = 10;
vector<char> buffer(a, 'a');
uint32_t b = htonl(a);
TC_NetWorkBuffer nb(NULL);
nb.addBuffer((const char *) &b, sizeof(b));
nb.addBuffer(buffer);
uint32_t c = nb.getValueOf4();
ASSERT_TRUE(c == a);
ASSERT_TRUE(nb.moveHeader(sizeof(b)));
vector<char> resBuffer;
ASSERT_TRUE(nb.getHeader(c, resBuffer));
ASSERT_TRUE(buffer == resBuffer);
}
TEST_F(UtilNetworkBufferTest, testBuffer2) //此时使用的是TEST_F宏
{
uint32_t a = 10;
vector<char> buffer(a, 'a');
uint32_t b = htonl(a);
TC_NetWorkBuffer nb(NULL);
nb.addBuffer((const char *) &b, 1);
nb.addBuffer((const char *) &b + 1, 3);
nb.addBuffer(buffer);
uint32_t c = nb.getValueOf4();
ASSERT_TRUE(c == a);
ASSERT_TRUE(nb.moveHeader(sizeof(b)));
vector<char> resBuffer;
ASSERT_TRUE(nb.getHeader(c, resBuffer));
ASSERT_TRUE(buffer == resBuffer);
}
TEST_F(UtilNetworkBufferTest, testBuffer3) //此时使用的是TEST_F宏
{
uint32_t a = 10;
vector<char> buffer(a, 'a');
uint32_t b = htonl(a);
TC_NetWorkBuffer nb(NULL);
nb.addBuffer((const char *) &b, 3);
nb.addBuffer((const char *) &b + 3, 1);
nb.addBuffer(buffer.data(), 5);
nb.addBuffer(buffer.data() + 5, a - 5);
uint32_t c = nb.getValueOf4();
ASSERT_TRUE(c == a);
ASSERT_TRUE(nb.moveHeader(sizeof(c)));
vector<char> resBuffer;
ASSERT_TRUE(nb.getHeader(c, resBuffer));
ASSERT_TRUE(buffer == resBuffer);
}
TEST_F(UtilNetworkBufferTest, testBuffer4) //此时使用的是TEST_F宏
{
uint32_t a = 10;
vector<char> buffer(a, 'a');
uint32_t b = htonl(a);
TC_NetWorkBuffer nb(NULL);
nb.addBuffer((const char*)&b, 2);
nb.addBuffer((const char*)&b + 2, 1);
nb.addBuffer((const char*)&b + 3, 1);
nb.addBuffer(buffer.data(), 3);
nb.addBuffer(buffer.data() + 3, 4);
nb.addBuffer(buffer.data() + 3, a - 3 - 4);
uint32_t c = nb.getValueOf4();
ASSERT_TRUE(c == a);
ASSERT_TRUE(nb.moveHeader(sizeof(c)));
vector<char> resBuffer;
ASSERT_TRUE(nb.getHeader(c, resBuffer));
ASSERT_TRUE(buffer == resBuffer);
}
TEST_F(UtilNetworkBufferTest, testBuffer5) //此时使用的是TEST_F宏
{
uint16_t a = 10;
vector<char> buffer(a, 10);
uint16_t b = htons(a);
TC_NetWorkBuffer nb(NULL);
nb.addBuffer((const char *) &b, sizeof(b));
nb.addBuffer(buffer);
uint16_t c = nb.getValueOf2();
ASSERT_TRUE(c == a);
ASSERT_TRUE(nb.moveHeader(sizeof(b)));
vector<char> resBuffer;
ASSERT_TRUE(nb.getHeader(c, resBuffer));
ASSERT_TRUE(buffer == resBuffer);
}
TEST_F(UtilNetworkBufferTest, testBuffer6) //此时使用的是TEST_F宏
{
uint16_t a = 10;
vector<char> buffer(a, 10);
uint16_t b = htons(a);
TC_NetWorkBuffer nb(NULL);
nb.addBuffer((const char*)&b, 1);
nb.addBuffer((const char*)&b + 1, 1);
nb.addBuffer(buffer);
uint16_t c = nb.getValueOf2();
ASSERT_TRUE(c == a);
ASSERT_TRUE(nb.moveHeader(sizeof(b)));
vector<char> resBuffer;
ASSERT_TRUE(nb.getHeader(c, resBuffer));
ASSERT_TRUE(buffer == resBuffer);
}
TEST_F(UtilNetworkBufferTest, testBuffer7) //此时使用的是TEST_F宏
{
uint16_t a = 10;
vector<char> buffer(a, 10);
uint16_t b = htons(a);
TC_NetWorkBuffer nb(NULL);
nb.addBuffer((const char*)&b, 2);
nb.addBuffer(buffer.data(), 5);
nb.addBuffer(buffer.data() + 5, a - 5);
uint16_t c = nb.getValueOf2();
ASSERT_TRUE(c == a);
ASSERT_TRUE(nb.moveHeader(sizeof(c)));
vector<char> resBuffer;
ASSERT_TRUE(nb.getHeader(c, resBuffer));
ASSERT_TRUE(buffer == resBuffer);
}
TEST_F(UtilNetworkBufferTest, testBuffer8) //此时使用的是TEST_F宏
{
uint16_t a = 10;
vector<char> buffer(a, 10);
uint16_t b = htons(a);
TC_NetWorkBuffer nb(NULL);
nb.addBuffer((const char*)&b, 1);
nb.addBuffer((const char*)&b + 1, 1);
nb.addBuffer(buffer.data(), 3);
nb.addBuffer(buffer.data() + 3, 4);
nb.addBuffer(buffer.data() + 3, a - 3 - 4);
uint16_t c = nb.getValueOf2();
ASSERT_TRUE(c == a);
ASSERT_TRUE(nb.moveHeader(sizeof(c)));
vector<char> resBuffer;
ASSERT_TRUE(nb.getHeader(c, resBuffer));
ASSERT_TRUE(buffer == resBuffer);
}
TEST_F(UtilNetworkBufferTest, testIterator)
{
TC_NetWorkBuffer buff(NULL);
buff.addBuffer("GET www.qq.com/a/b?name=value&ccc=ddd HTTP/1.1\r\n");
buff.addBuffer("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
buff.addBuffer("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
buff.addBuffer("Accept-Encoding: gzip\r\n");
buff.addBuffer("Connection: close\r\n");
buff.addBuffer("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
TC_NetWorkBuffer::buffer_iterator it = buff.begin();
// cout << "testIterator-------------------------------------" << endl;
ostringstream os;
while(it != buff.end())
{
os << *it;
++it;
}
ASSERT_TRUE(os.str() == buff.getBuffersString());
}
TEST_F(UtilNetworkBufferTest, testIteratorRandom)
{
TC_NetWorkBuffer buff(NULL);
buff.addBuffer("GET www.qq.com/a/b?name=value&ccc=ddd HTTP/1.1\r\n");
buff.addBuffer("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
buff.addBuffer("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
buff.addBuffer("Accept-Encoding: gzip\r\n");
buff.addBuffer("Connection: close\r\n");
buff.addBuffer("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
// cout << "testIteratorRandom-------------------------------------" << endl;
TC_NetWorkBuffer::buffer_iterator it = buff.begin();
// for(size_t i = 0; i < buff.getBufferLength(); ++i)
// {
// cout << *(it + i);
// }
ASSERT_TRUE((it + 10) - (it + 5) == 5);
ASSERT_TRUE((it + 44) - (it + 12 ) == 32);
ASSERT_TRUE((it + 54) - (it + 2) == 52);
ASSERT_TRUE((it + 111111) == buff.end());
ASSERT_TRUE((it - 111111) == buff.end());
}
TEST_F(UtilNetworkBufferTest, testFind)
{
vector<string> sbuff;
sbuff.push_back("GET www.qq.com/a/b?name=value&ccc=ddd HTTP/1.1\r\n");
sbuff.push_back("Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\n");
sbuff.push_back("Accept-Charset: utf-8,gb2321;q=0.7,*;q=0.7\r\n");
sbuff.push_back("Accept-Encoding: gzip\r\n");
sbuff.push_back("Connection: close\r\n");
sbuff.push_back("User-Agent: E71/SymbianOS/9.1 Series60/3.0\r\n\r\n");
string header;
for(auto s : sbuff)
{
header += s;
}
string s = header + "abccccddddddd";
TC_NetWorkBuffer buff(NULL);
buff.addBuffer(s.c_str(), s.size());
string headerBuf;
headerBuf = buff.getPrefixBuffer<string>("xxx", 3);
ASSERT_TRUE(headerBuf.empty());
string find = "Accept-Encoding:";
auto it = std::search(buff.begin(), buff.end(), find.c_str(), find.c_str() + find.size());
ASSERT_TRUE(it != buff.end());
ASSERT_TRUE(it - buff.begin() == sbuff[0].size() + sbuff[1].size() + sbuff[2].size());
find = "accept-encoding:";
it = std::search(buff.begin(), buff.end(), find.c_str(), find.c_str() + find.size(), [](char x, char y){return toupper(x) == toupper(y);});
ASSERT_TRUE(it != buff.end());
ASSERT_TRUE(it - buff.begin() == sbuff[0].size() + sbuff[1].size() + sbuff[2].size());
string sep = "\r\n\r\n";
headerBuf = buff.getPrefixBuffer<string>(sep.c_str(), sep.size());
ASSERT_TRUE(header == headerBuf + sep);
sep = "\r\n";
headerBuf = buff.getPrefixBuffer<string>(sep.c_str(), sep.size());
ASSERT_TRUE(sbuff[0] == headerBuf + sep);
buff.moveHeader(sbuff[0].size());
headerBuf = buff.getPrefixBuffer<string>(sep.c_str(), sep.size());
ASSERT_TRUE(sbuff[1] == headerBuf + sep);
buff.moveHeader(sbuff[1].size());
headerBuf = buff.getPrefixBuffer<string>(sep.c_str(), sep.size());
ASSERT_TRUE(sbuff[2] == headerBuf + sep);
buff.moveHeader(sbuff[2].size());
headerBuf = buff.getPrefixBuffer<string>(sep.c_str(), sep.size());
ASSERT_TRUE(sbuff[3] == headerBuf + sep);
buff.moveHeader(sbuff[3].size());
}
TEST_F(UtilNetworkBufferTest, testAlloc)
{
string buffer(100, 'a' );
TC_NetWorkBuffer::Buffer buff;
buff.addBuffer(buffer);
ASSERT_TRUE(buff.capacity() == buffer.size());
ASSERT_TRUE(buff.readIdx() == 0);
ASSERT_TRUE(buff.writeIdx() == buffer.size());
ASSERT_TRUE(buff.length() == buffer.size());
ASSERT_TRUE(buff.left() == 0);
buff.addReadIdx(10);
ASSERT_TRUE(buff.readIdx() == 10);
ASSERT_TRUE(buff.length() == buffer.size()-10);
buff.compact();
ASSERT_TRUE(buff.readIdx() == 0);
ASSERT_TRUE(buff.writeIdx() == buffer.size() - 10);
ASSERT_TRUE(buff.length() == buffer.size()-10);
buff.addReadIdx(15);
buff.expansion(120);
ASSERT_TRUE(buff.readIdx() == 0);
ASSERT_TRUE(buff.writeIdx() == buffer.size() - 10 - 15);
buff.addBuffer(buffer);
ASSERT_TRUE(buff.capacity() == 175);
ASSERT_TRUE(buff.readIdx() == 0);
}
TEST_F(UtilNetworkBufferTest, testGetOrCreateBuffer)
{
TC_NetWorkBuffer buff(NULL);
shared_ptr<TC_NetWorkBuffer::Buffer> data;
{
data = buff.getOrCreateBuffer(100, 300);
ASSERT_TRUE(buff.listSize() == 1);
ASSERT_TRUE(data->capacity() == 300);
ASSERT_TRUE(data->readIdx() == 0);
ASSERT_TRUE(data->length() == 0);
}
LOG_CONSOLE_DEBUG << endl;
{
data->addWriteIdx(50);
data = buff.getOrCreateBuffer(100, 300);
ASSERT_TRUE(buff.listSize() == 1);
ASSERT_TRUE(data->capacity() == 300);
ASSERT_TRUE(data->readIdx() == 0);
ASSERT_TRUE(data->length() == 50);
}
{
data->addWriteIdx(200);
data->addReadIdx(200);
data = buff.getOrCreateBuffer(100, 300);
ASSERT_TRUE(buff.listSize() == 1);
ASSERT_TRUE(data->capacity() == 300);
ASSERT_TRUE(data->readIdx() == 0);
ASSERT_TRUE(data->length() == 50);
}
{
data->addWriteIdx(200);
data = buff.getOrCreateBuffer(100, 300);
ASSERT_TRUE(buff.listSize() == 2);
ASSERT_TRUE(data->capacity() == 300);
ASSERT_TRUE(data->readIdx() == 0);
ASSERT_TRUE(data->length() == 0);
}
{
buff.clearBuffers();
ASSERT_TRUE(buff.listSize() == 0);
}
buff.clearBuffers();
string a(794, 'a');
buff.addBuffer(a.c_str(), a.size());
string b(6307, 'b');
buff.addBuffer(b.c_str(), b.size());
}
TEST_F(UtilNetworkBufferTest, testCompact)
{
srand(time(NULL));
shared_ptr<TC_NetWorkBuffer::Buffer> data = std::make_shared<TC_NetWorkBuffer::Buffer>();
vector<char> buff;
for (size_t i = 0; i < 50; i++)
{
buff.push_back('a' + rand() % 26);
}
data->addBuffer(buff);
data->addReadIdx(10);
data->compact();
ASSERT_TRUE(TC_Port::strncasecmp(data->buffer(), &buff[10], data->length()) == 0);
}

View File

@ -0,0 +1,58 @@
#include "util/tc_timer.h"
#include "util/tc_logger.h"
#include "util/tc_common.h"
#include "util/tc_thread_pool.h"
#include "gtest/gtest.h"
#include <iostream>
#include <vector>
using namespace std;
using namespace tars;
class UtilThreadPollTest : public testing::Test
{
public:
//添加日志
static void SetUpTestCase()
{
}
static void TearDownTestCase()
{
}
virtual void SetUp() //TEST跑之前会执行SetUp
{
}
virtual void TearDown() //TEST跑完之后会执行TearDown
{
}
};
class TestClass
{
public:
~TestClass()
{
// LOG_CONSOLE_DEBUG << endl;
}
void test(int i)
{
_data.push_back(i);
}
vector<int> _data;
};
TEST_F(UtilThreadPollTest, testDecontructor)
{
TC_ThreadPool tpool;
tpool.init(5);
shared_ptr<TestClass> tPtr = std::make_shared<TestClass>();
for(int i = 0; i < 5; i++)
{
tpool.exec(std::bind(&TestClass::test, tPtr.get(), std::placeholders::_1), i);
}
tpool.stop();
}

247
unit-test/util/test_tc_timer.cpp Executable file
View File

@ -0,0 +1,247 @@
#include "util/tc_timer.h"
#include "util/tc_common.h"
#include "util/tc_cron.h"
#include "util/tc_epoller.h"
#include "gtest/gtest.h"
#include <iostream>
#include <vector>
using namespace std;
using namespace tars;
class UtilTimerTest : public testing::Test
{
public:
//添加日志
static void SetUpTestCase()
{
}
static void TearDownTestCase()
{
}
virtual void SetUp() //TEST跑之前会执行SetUp
{
}
virtual void TearDown() //TEST跑完之后会执行TearDown
{
}
};
class TestClass
{
public:
void test1()
{
_data.push_back(std::make_pair(TNOWMS, 0));
}
void test2(int64_t i)
{
_data.push_back(std::make_pair(TNOWMS, i));
}
void test3(int i)
{
_data.push_back(std::make_pair(TNOWMS, i));
}
void testCron()
{
_data.push_back(std::make_pair(TNOWMS, 0));
}
void testCron2()
{
_data.push_back(std::make_pair(TNOWMS, 0));
}
vector<pair<int64_t, int64_t>> _data;
};
TEST_F(UtilTimerTest, testDelayTask1)
{
TC_Timer timer;
timer.startTimer(1);
shared_ptr<TestClass> tPtr = std::make_shared<TestClass>();
timer.postDelayed(100, std::bind(&TestClass::test2, tPtr.get(), std::placeholders::_1), 111);
TC_Common::msleep(106);
ASSERT_TRUE(tPtr->_data.size() == 1);
timer.stopTimer();
}
TEST_F(UtilTimerTest, testDelayTask2)
{
TC_Timer timer;
timer.startTimer(1);
shared_ptr<TestClass> tPtr = std::make_shared<TestClass>();
uint64_t id2 = timer.postDelayed(100, std::bind(&TestClass::test2, tPtr.get(), std::placeholders::_1), 111);
TC_Common::msleep(5);
ASSERT_TRUE(tPtr->_data.size() == 0);
timer.erase(id2);
timer.stopTimer();
}
TEST_F(UtilTimerTest, testRepeatTask)
{
TC_Timer timer;
shared_ptr<TestClass> tPtr = std::make_shared<TestClass>();
timer.startTimer(1);
uint64_t id2 = timer.postRepeated(50, false, std::bind(&TestClass::test1, tPtr.get()));
TC_Common::msleep(1080);
//由于精度原因, 有一定误差
ASSERT_TRUE(tPtr->_data.size() >= 20);
ASSERT_TRUE(tPtr->_data.size() <= 21);
for (int i = 0; i < 9; i++)
{
int diff = fabs(tPtr->_data[i + 1].first - tPtr->_data[i].first);
ASSERT_TRUE(diff <= 56);
}
timer.erase(id2);
TC_Common::msleep(100);
ASSERT_TRUE(tPtr->_data.size() >= 20);
ASSERT_TRUE(tPtr->_data.size() <= 21);
timer.stopTimer();
}
struct AAA
{
AAA() { };
~AAA() { };
void test() {}
int xxx = 100;
};
void fff(const std::shared_ptr<AAA>& ppp)
{
ppp->xxx++;
// cout << TC_Common::now2ms() << ", " << ppp->xxx << endl;
}
TEST_F(UtilTimerTest, testTimerMem)
{
TC_Timer timer;
timer.startTimer(1);
std::shared_ptr<AAA> pa = std::make_shared<AAA>();
//right
{
auto func = [pa]
{
fff(pa);
};
int xxx = pa->xxx;
timer.postDelayed(100, func);
TC_Common::msleep(120);
ASSERT_TRUE(pa->xxx - xxx == 1);
}
//right
{
auto funcb = std::bind(fff, pa);
int xxx = pa->xxx;
timer.postDelayed(100, funcb);
TC_Common::msleep(120);
ASSERT_TRUE(pa->xxx - xxx == 1);
}
//right
{
int xxx = pa->xxx;
timer.postDelayed(100, fff, pa);
TC_Common::msleep(120);
ASSERT_TRUE(pa->xxx - xxx == 1);
}
//right
{
int xxx = pa->xxx;
timer.postDelayed(100, std::bind(fff, std::ref(pa)));
TC_Common::msleep(120);
ASSERT_TRUE(pa->xxx - xxx == 1);
}
//wrong, unkown reason
// if (1)
{
int xxx = pa->xxx;
timer.postDelayed(100, std::bind(fff, pa));
TC_Common::msleep(120);
ASSERT_TRUE(pa->xxx - xxx == 1);
}
timer.stopTimer();
}
TEST_F(UtilTimerTest, testTimerRepeatMem)
{
TC_Timer timer;
timer.startTimer(1);
std::shared_ptr<AAA> pa = std::make_shared<AAA>();
int xxx = pa->xxx;
auto func = [pa] {
fff(pa);
};
int64_t taskId = timer.postRepeated(50, false, func);
TC_Common::msleep(1020);
//注意timer有精度的问题, 精度只能到5ms, 所以这里有一定的误差!
int diff = pa->xxx - xxx;
ASSERT_TRUE(diff >= 19);
ASSERT_TRUE(diff <= 20);
timer.erase(taskId);
TC_Common::msleep(1000);
diff = pa->xxx - xxx;
ASSERT_TRUE(diff >= 19);
ASSERT_TRUE(diff <= 20);
timer.stopTimer();
}
TEST_F(UtilTimerTest, testRepeatUseCount)
{
TC_Timer timer;
timer.startTimer(1);
std::shared_ptr<AAA> pa = std::make_shared<AAA>();
ASSERT_TRUE(pa.use_count() == 1);
int64_t taskId = timer.postRepeated(50, false, std::bind(&AAA::test, pa));
ASSERT_TRUE(pa.use_count() == 2);
timer.erase(taskId);
ASSERT_TRUE(pa.use_count() == 1);
timer.postRepeated(50, false, std::bind(&AAA::test, pa));
ASSERT_TRUE(pa.use_count() == 2);
timer.clear();
ASSERT_TRUE(pa.use_count() == 1);
timer.stopTimer();
}