Moving from govendor to dep, updated dependencies (#48)
* Moving from govendor to dep. * Making the pull request template more friendly. * Fixing akward space in PR template. * goimports run on whole project using ` goimports -w $(find . -type f -name '*.go' -not -path "./vendor/*" -not -path "./gen-go/*")` source of command: https://gist.github.com/bgentry/fd1ffef7dbde01857f66
This commit is contained in:
parent
9631aa3aab
commit
8d445c1c77
2186 changed files with 400410 additions and 352 deletions
47
vendor/git.apache.org/thrift.git/lib/cpp/test/AllProtocolTests.cpp
generated
vendored
Normal file
47
vendor/git.apache.org/thrift.git/lib/cpp/test/AllProtocolTests.cpp
generated
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <stdio.h>
|
||||
|
||||
#include <thrift/protocol/TBinaryProtocol.h>
|
||||
#include <thrift/protocol/TCompactProtocol.h>
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
|
||||
#define BOOST_TEST_MODULE AllProtocolTests
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "AllProtocolTests.tcc"
|
||||
|
||||
using namespace apache::thrift;
|
||||
using namespace apache::thrift::protocol;
|
||||
using namespace apache::thrift::transport;
|
||||
|
||||
char errorMessage[ERR_LEN];
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_binary_protocol) {
|
||||
testProtocol<TBinaryProtocol>("TBinaryProtocol");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_little_binary_protocol) {
|
||||
testProtocol<TLEBinaryProtocol>("TLEBinaryProtocol");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_compact_protocol) {
|
||||
testProtocol<TCompactProtocol>("TCompactProtocol");
|
||||
}
|
225
vendor/git.apache.org/thrift.git/lib/cpp/test/AllProtocolTests.tcc
generated
vendored
Normal file
225
vendor/git.apache.org/thrift.git/lib/cpp/test/AllProtocolTests.tcc
generated
vendored
Normal file
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 _THRIFT_TEST_GENERICPROTOCOLTEST_TCC_
|
||||
#define _THRIFT_TEST_GENERICPROTOCOLTEST_TCC_ 1
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include <thrift/protocol/TBinaryProtocol.h>
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
#include <thrift/Thrift.h>
|
||||
|
||||
#include "GenericHelpers.h"
|
||||
|
||||
using boost::shared_ptr;
|
||||
using namespace apache::thrift;
|
||||
using namespace apache::thrift::protocol;
|
||||
using namespace apache::thrift::transport;
|
||||
|
||||
#define ERR_LEN 512
|
||||
extern char errorMessage[ERR_LEN];
|
||||
|
||||
template <typename TProto, typename Val>
|
||||
void testNaked(Val val) {
|
||||
shared_ptr<TTransport> transport(new TMemoryBuffer());
|
||||
shared_ptr<TProtocol> protocol(new TProto(transport));
|
||||
|
||||
GenericIO::write(protocol, val);
|
||||
Val out;
|
||||
GenericIO::read(protocol, out);
|
||||
if (out != val) {
|
||||
THRIFT_SNPRINTF(errorMessage,
|
||||
ERR_LEN,
|
||||
"Invalid naked test (type: %s)",
|
||||
ClassNames::getName<Val>());
|
||||
throw TException(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TProto, TType type, typename Val>
|
||||
void testField(const Val val) {
|
||||
shared_ptr<TTransport> transport(new TMemoryBuffer());
|
||||
shared_ptr<TProtocol> protocol(new TProto(transport));
|
||||
|
||||
protocol->writeStructBegin("test_struct");
|
||||
protocol->writeFieldBegin("test_field", type, (int16_t)15);
|
||||
|
||||
GenericIO::write(protocol, val);
|
||||
|
||||
protocol->writeFieldEnd();
|
||||
protocol->writeStructEnd();
|
||||
|
||||
std::string name;
|
||||
TType fieldType;
|
||||
int16_t fieldId;
|
||||
|
||||
protocol->readStructBegin(name);
|
||||
protocol->readFieldBegin(name, fieldType, fieldId);
|
||||
|
||||
if (fieldId != 15) {
|
||||
THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid ID (type: %s)", typeid(val).name());
|
||||
throw TException(errorMessage);
|
||||
}
|
||||
if (fieldType != type) {
|
||||
THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid Field Type (type: %s)", typeid(val).name());
|
||||
throw TException(errorMessage);
|
||||
}
|
||||
|
||||
Val out;
|
||||
GenericIO::read(protocol, out);
|
||||
|
||||
if (out != val) {
|
||||
THRIFT_SNPRINTF(errorMessage, ERR_LEN, "Invalid value read (type: %s)", typeid(val).name());
|
||||
throw TException(errorMessage);
|
||||
}
|
||||
|
||||
protocol->readFieldEnd();
|
||||
protocol->readStructEnd();
|
||||
}
|
||||
|
||||
template <typename TProto>
|
||||
void testMessage() {
|
||||
struct TMessage {
|
||||
const char* name;
|
||||
TMessageType type;
|
||||
int32_t seqid;
|
||||
} messages[] = {{"short message name", T_CALL, 0},
|
||||
{"1", T_REPLY, 12345},
|
||||
{"loooooooooooooooooooooooooooooooooong", T_EXCEPTION, 1 << 16},
|
||||
{"one way push", T_ONEWAY, 12},
|
||||
{"Janky", T_CALL, 0}};
|
||||
const int messages_count = sizeof(messages) / sizeof(TMessage);
|
||||
|
||||
for (int i = 0; i < messages_count; i++) {
|
||||
shared_ptr<TTransport> transport(new TMemoryBuffer());
|
||||
shared_ptr<TProtocol> protocol(new TProto(transport));
|
||||
|
||||
protocol->writeMessageBegin(messages[i].name, messages[i].type, messages[i].seqid);
|
||||
protocol->writeMessageEnd();
|
||||
|
||||
std::string name;
|
||||
TMessageType type;
|
||||
int32_t seqid;
|
||||
|
||||
protocol->readMessageBegin(name, type, seqid);
|
||||
if (name != messages[i].name || type != messages[i].type || seqid != messages[i].seqid) {
|
||||
throw TException("readMessageBegin failed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TProto>
|
||||
void testProtocol(const char* protoname) {
|
||||
try {
|
||||
testNaked<TProto, int8_t>((int8_t)123);
|
||||
|
||||
for (int32_t i = 0; i < 128; i++) {
|
||||
testField<TProto, T_BYTE, int8_t>((int8_t)i);
|
||||
testField<TProto, T_BYTE, int8_t>((int8_t)-i);
|
||||
}
|
||||
|
||||
testNaked<TProto, int16_t>((int16_t)0);
|
||||
testNaked<TProto, int16_t>((int16_t)1);
|
||||
testNaked<TProto, int16_t>((int16_t)15000);
|
||||
testNaked<TProto, int16_t>((int16_t)0x7fff);
|
||||
testNaked<TProto, int16_t>((int16_t)-1);
|
||||
testNaked<TProto, int16_t>((int16_t)-15000);
|
||||
testNaked<TProto, int16_t>((int16_t)-0x7fff);
|
||||
testNaked<TProto, int16_t>((std::numeric_limits<int16_t>::min)());
|
||||
testNaked<TProto, int16_t>((std::numeric_limits<int16_t>::max)());
|
||||
|
||||
testField<TProto, T_I16, int16_t>((int16_t)0);
|
||||
testField<TProto, T_I16, int16_t>((int16_t)1);
|
||||
testField<TProto, T_I16, int16_t>((int16_t)7);
|
||||
testField<TProto, T_I16, int16_t>((int16_t)150);
|
||||
testField<TProto, T_I16, int16_t>((int16_t)15000);
|
||||
testField<TProto, T_I16, int16_t>((int16_t)0x7fff);
|
||||
testField<TProto, T_I16, int16_t>((int16_t)-1);
|
||||
testField<TProto, T_I16, int16_t>((int16_t)-7);
|
||||
testField<TProto, T_I16, int16_t>((int16_t)-150);
|
||||
testField<TProto, T_I16, int16_t>((int16_t)-15000);
|
||||
testField<TProto, T_I16, int16_t>((int16_t)-0x7fff);
|
||||
|
||||
testNaked<TProto, int32_t>(0);
|
||||
testNaked<TProto, int32_t>(1);
|
||||
testNaked<TProto, int32_t>(15000);
|
||||
testNaked<TProto, int32_t>(0xffff);
|
||||
testNaked<TProto, int32_t>(-1);
|
||||
testNaked<TProto, int32_t>(-15000);
|
||||
testNaked<TProto, int32_t>(-0xffff);
|
||||
testNaked<TProto, int32_t>((std::numeric_limits<int32_t>::min)());
|
||||
testNaked<TProto, int32_t>((std::numeric_limits<int32_t>::max)());
|
||||
|
||||
testField<TProto, T_I32, int32_t>(0);
|
||||
testField<TProto, T_I32, int32_t>(1);
|
||||
testField<TProto, T_I32, int32_t>(7);
|
||||
testField<TProto, T_I32, int32_t>(150);
|
||||
testField<TProto, T_I32, int32_t>(15000);
|
||||
testField<TProto, T_I32, int32_t>(31337);
|
||||
testField<TProto, T_I32, int32_t>(0xffff);
|
||||
testField<TProto, T_I32, int32_t>(0xffffff);
|
||||
testField<TProto, T_I32, int32_t>(-1);
|
||||
testField<TProto, T_I32, int32_t>(-7);
|
||||
testField<TProto, T_I32, int32_t>(-150);
|
||||
testField<TProto, T_I32, int32_t>(-15000);
|
||||
testField<TProto, T_I32, int32_t>(-0xffff);
|
||||
testField<TProto, T_I32, int32_t>(-0xffffff);
|
||||
testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::min)());
|
||||
testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::max)());
|
||||
testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::min)() + 10);
|
||||
testNaked<TProto, int64_t>((std::numeric_limits<int32_t>::max)() - 16);
|
||||
testNaked<TProto, int64_t>((std::numeric_limits<int64_t>::min)());
|
||||
testNaked<TProto, int64_t>((std::numeric_limits<int64_t>::max)());
|
||||
|
||||
testNaked<TProto, int64_t>(0);
|
||||
for (int64_t i = 0; i < 62; i++) {
|
||||
testNaked<TProto, int64_t>(1L << i);
|
||||
testNaked<TProto, int64_t>(-(1L << i));
|
||||
}
|
||||
|
||||
testField<TProto, T_I64, int64_t>(0);
|
||||
for (int i = 0; i < 62; i++) {
|
||||
testField<TProto, T_I64, int64_t>(1L << i);
|
||||
testField<TProto, T_I64, int64_t>(-(1L << i));
|
||||
}
|
||||
|
||||
testNaked<TProto, double>(123.456);
|
||||
|
||||
testNaked<TProto, std::string>("");
|
||||
testNaked<TProto, std::string>("short");
|
||||
testNaked<TProto, std::string>("borderlinetiny");
|
||||
testNaked<TProto, std::string>("a bit longer than the smallest possible");
|
||||
testNaked<TProto, std::string>("\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA"); // kinda binary test
|
||||
|
||||
testField<TProto, T_STRING, std::string>("");
|
||||
testField<TProto, T_STRING, std::string>("short");
|
||||
testField<TProto, T_STRING, std::string>("borderlinetiny");
|
||||
testField<TProto, T_STRING, std::string>("a bit longer than the smallest possible");
|
||||
|
||||
testMessage<TProto>();
|
||||
|
||||
printf("%s => OK\n", protoname);
|
||||
} catch (TException e) {
|
||||
THRIFT_SNPRINTF(errorMessage, ERR_LEN, "%s => Test FAILED: %s", protoname, e.what());
|
||||
throw TException(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
70
vendor/git.apache.org/thrift.git/lib/cpp/test/Base64Test.cpp
generated
vendored
Normal file
70
vendor/git.apache.org/thrift.git/lib/cpp/test/Base64Test.cpp
generated
vendored
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <boost/test/auto_unit_test.hpp>
|
||||
#include <thrift/protocol/TBase64Utils.h>
|
||||
|
||||
using apache::thrift::protocol::base64_encode;
|
||||
using apache::thrift::protocol::base64_decode;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(Base64Test)
|
||||
|
||||
void setupTestData(int i, uint8_t* data, int& len) {
|
||||
len = 0;
|
||||
do {
|
||||
data[len] = (uint8_t)(i & 0xFF);
|
||||
i >>= 8;
|
||||
len++;
|
||||
} while ((len < 3) && (i != 0));
|
||||
|
||||
BOOST_ASSERT(i == 0);
|
||||
}
|
||||
|
||||
void checkEncoding(uint8_t* data, int len) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
BOOST_ASSERT(isalnum(data[i]) || data[i] == '/' || data[i] == '+');
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_Base64_Encode_Decode) {
|
||||
int len;
|
||||
uint8_t testInput[3];
|
||||
uint8_t testOutput[4];
|
||||
|
||||
// Test all possible encoding / decoding cases given the
|
||||
// three byte limit for base64_encode.
|
||||
|
||||
for (int i = 0xFFFFFF; i >= 0; i--) {
|
||||
|
||||
// fill testInput based on i
|
||||
setupTestData(i, testInput, len);
|
||||
|
||||
// encode the test data, then decode it again
|
||||
base64_encode(testInput, len, testOutput);
|
||||
|
||||
// verify each byte has a valid Base64 value (alphanumeric or either + or /)
|
||||
checkEncoding(testOutput, len);
|
||||
|
||||
// decode output and check that it matches input
|
||||
base64_decode(testOutput, len + 1);
|
||||
BOOST_ASSERT(0 == memcmp(testInput, testOutput, len));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
243
vendor/git.apache.org/thrift.git/lib/cpp/test/Benchmark.cpp
generated
vendored
Normal file
243
vendor/git.apache.org/thrift.git/lib/cpp/test/Benchmark.cpp
generated
vendored
Normal file
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include "thrift/transport/TBufferTransports.h"
|
||||
#include "thrift/protocol/TBinaryProtocol.h"
|
||||
#include "gen-cpp/DebugProtoTest_types.h"
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
class Timer {
|
||||
public:
|
||||
timeval vStart;
|
||||
|
||||
Timer() { THRIFT_GETTIMEOFDAY(&vStart, 0); }
|
||||
void start() { THRIFT_GETTIMEOFDAY(&vStart, 0); }
|
||||
|
||||
double frame() {
|
||||
timeval vEnd;
|
||||
THRIFT_GETTIMEOFDAY(&vEnd, 0);
|
||||
double dstart = vStart.tv_sec + ((double)vStart.tv_usec / 1000000.0);
|
||||
double dend = vEnd.tv_sec + ((double)vEnd.tv_usec / 1000000.0);
|
||||
return dend - dstart;
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
using namespace std;
|
||||
using namespace thrift::test::debug;
|
||||
using namespace apache::thrift::transport;
|
||||
using namespace apache::thrift::protocol;
|
||||
using namespace boost;
|
||||
|
||||
OneOfEach ooe;
|
||||
ooe.im_true = true;
|
||||
ooe.im_false = false;
|
||||
ooe.a_bite = 0x7f;
|
||||
ooe.integer16 = 27000;
|
||||
ooe.integer32 = 1 << 24;
|
||||
ooe.integer64 = (uint64_t)6000 * 1000 * 1000;
|
||||
ooe.double_precision = M_PI;
|
||||
ooe.some_characters = "JSON THIS! \"\1";
|
||||
ooe.zomg_unicode = "\xd7\n\a\t";
|
||||
ooe.base64 = "\1\2\3\255";
|
||||
|
||||
int num = 100000;
|
||||
boost::shared_ptr<TMemoryBuffer> buf(new TMemoryBuffer(num*1000));
|
||||
|
||||
uint8_t* data = NULL;
|
||||
uint32_t datasize = 0;
|
||||
|
||||
{
|
||||
buf->resetBuffer();
|
||||
TBinaryProtocolT<TMemoryBuffer> prot(buf);
|
||||
double elapsed = 0.0;
|
||||
Timer timer;
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
ooe.write(&prot);
|
||||
}
|
||||
elapsed = timer.frame();
|
||||
cout << "Write big endian: " << num / (1000 * elapsed) << " kHz" << endl;
|
||||
}
|
||||
|
||||
buf->getBuffer(&data, &datasize);
|
||||
|
||||
{
|
||||
boost::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
|
||||
TBinaryProtocolT<TMemoryBuffer> prot(buf2);
|
||||
OneOfEach ooe2;
|
||||
double elapsed = 0.0;
|
||||
Timer timer;
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
ooe2.read(&prot);
|
||||
}
|
||||
elapsed = timer.frame();
|
||||
cout << " Read big endian: " << num / (1000 * elapsed) << " kHz" << endl;
|
||||
}
|
||||
|
||||
{
|
||||
buf->resetBuffer();
|
||||
TBinaryProtocolT<TMemoryBuffer, TNetworkLittleEndian> prot(buf);
|
||||
double elapsed = 0.0;
|
||||
Timer timer;
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
ooe.write(&prot);
|
||||
}
|
||||
elapsed = timer.frame();
|
||||
cout << "Write little endian: " << num / (1000 * elapsed) << " kHz" << endl;
|
||||
}
|
||||
|
||||
{
|
||||
OneOfEach ooe2;
|
||||
boost::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
|
||||
TBinaryProtocolT<TMemoryBuffer, TNetworkLittleEndian> prot(buf2);
|
||||
double elapsed = 0.0;
|
||||
Timer timer;
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
ooe2.read(&prot);
|
||||
}
|
||||
elapsed = timer.frame();
|
||||
cout << " Read little endian: " << num / (1000 * elapsed) << " kHz" << endl;
|
||||
}
|
||||
|
||||
{
|
||||
buf->resetBuffer();
|
||||
TBinaryProtocolT<TMemoryBuffer> prot(buf);
|
||||
double elapsed = 0.0;
|
||||
Timer timer;
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
ooe.write(&prot);
|
||||
}
|
||||
elapsed = timer.frame();
|
||||
cout << "Write big endian: " << num / (1000 * elapsed) << " kHz" << endl;
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
|
||||
TBinaryProtocolT<TMemoryBuffer> prot(buf2);
|
||||
OneOfEach ooe2;
|
||||
double elapsed = 0.0;
|
||||
Timer timer;
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
ooe2.read(&prot);
|
||||
}
|
||||
elapsed = timer.frame();
|
||||
cout << " Read big endian: " << num / (1000 * elapsed) << " kHz" << endl;
|
||||
}
|
||||
|
||||
|
||||
data = NULL;
|
||||
datasize = 0;
|
||||
num = 10000000;
|
||||
|
||||
ListDoublePerf listDoublePerf;
|
||||
listDoublePerf.field.reserve(num);
|
||||
for (int x = 0; x < num; ++x)
|
||||
listDoublePerf.field.push_back(double(x));
|
||||
|
||||
buf.reset(new TMemoryBuffer(num * 100));
|
||||
|
||||
{
|
||||
buf->resetBuffer();
|
||||
TBinaryProtocolT<TMemoryBuffer> prot(buf);
|
||||
double elapsed = 0.0;
|
||||
Timer timer;
|
||||
|
||||
listDoublePerf.write(&prot);
|
||||
elapsed = timer.frame();
|
||||
cout << "Double write big endian: " << num / (1000 * elapsed) << " kHz" << endl;
|
||||
}
|
||||
|
||||
buf->getBuffer(&data, &datasize);
|
||||
|
||||
{
|
||||
boost::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
|
||||
TBinaryProtocolT<TMemoryBuffer> prot(buf2);
|
||||
ListDoublePerf listDoublePerf2;
|
||||
double elapsed = 0.0;
|
||||
Timer timer;
|
||||
|
||||
listDoublePerf2.read(&prot);
|
||||
elapsed = timer.frame();
|
||||
cout << " Double read big endian: " << num / (1000 * elapsed) << " kHz" << endl;
|
||||
}
|
||||
|
||||
{
|
||||
buf->resetBuffer();
|
||||
TBinaryProtocolT<TMemoryBuffer, TNetworkLittleEndian> prot(buf);
|
||||
double elapsed = 0.0;
|
||||
Timer timer;
|
||||
|
||||
listDoublePerf.write(&prot);
|
||||
elapsed = timer.frame();
|
||||
cout << "Double write little endian: " << num / (1000 * elapsed) << " kHz" << endl;
|
||||
}
|
||||
|
||||
{
|
||||
ListDoublePerf listDoublePerf2;
|
||||
boost::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
|
||||
TBinaryProtocolT<TMemoryBuffer, TNetworkLittleEndian> prot(buf2);
|
||||
double elapsed = 0.0;
|
||||
Timer timer;
|
||||
|
||||
listDoublePerf2.read(&prot);
|
||||
elapsed = timer.frame();
|
||||
cout << " Double read little endian: " << num / (1000 * elapsed) << " kHz" << endl;
|
||||
}
|
||||
|
||||
{
|
||||
buf->resetBuffer();
|
||||
TBinaryProtocolT<TMemoryBuffer> prot(buf);
|
||||
double elapsed = 0.0;
|
||||
Timer timer;
|
||||
|
||||
listDoublePerf.write(&prot);
|
||||
elapsed = timer.frame();
|
||||
cout << "Double write big endian: " << num / (1000 * elapsed) << " kHz" << endl;
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<TMemoryBuffer> buf2(new TMemoryBuffer(data, datasize));
|
||||
TBinaryProtocolT<TMemoryBuffer> prot(buf2);
|
||||
ListDoublePerf listDoublePerf2;
|
||||
double elapsed = 0.0;
|
||||
Timer timer;
|
||||
|
||||
listDoublePerf2.read(&prot);
|
||||
elapsed = timer.frame();
|
||||
cout << " Double read big endian: " << num / (1000 * elapsed) << " kHz" << endl;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
361
vendor/git.apache.org/thrift.git/lib/cpp/test/CMakeLists.txt
generated
vendored
Normal file
361
vendor/git.apache.org/thrift.git/lib/cpp/test/CMakeLists.txt
generated
vendored
Normal file
|
@ -0,0 +1,361 @@
|
|||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# 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_directories(SYSTEM "${Boost_INCLUDE_DIRS}")
|
||||
|
||||
#Make sure gen-cpp files can be included
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
# Create the thrift C++ test library
|
||||
set(testgencpp_SOURCES
|
||||
gen-cpp/DebugProtoTest_types.cpp
|
||||
gen-cpp/DebugProtoTest_types.h
|
||||
gen-cpp/EnumTest_types.cpp
|
||||
gen-cpp/EnumTest_types.h
|
||||
gen-cpp/OptionalRequiredTest_types.cpp
|
||||
gen-cpp/OptionalRequiredTest_types.h
|
||||
gen-cpp/Recursive_types.cpp
|
||||
gen-cpp/Recursive_types.h
|
||||
gen-cpp/ThriftTest_types.cpp
|
||||
gen-cpp/ThriftTest_types.h
|
||||
gen-cpp/TypedefTest_types.cpp
|
||||
gen-cpp/TypedefTest_types.h
|
||||
ThriftTest_extras.cpp
|
||||
DebugProtoTest_extras.cpp
|
||||
)
|
||||
|
||||
add_library(testgencpp STATIC ${testgencpp_SOURCES})
|
||||
|
||||
set(testgencpp_cob_SOURCES
|
||||
gen-cpp/ChildService.cpp
|
||||
gen-cpp/ChildService.h
|
||||
gen-cpp/EmptyService.cpp
|
||||
gen-cpp/EmptyService.h
|
||||
gen-cpp/ParentService.cpp
|
||||
gen-cpp/ParentService.h
|
||||
gen-cpp/proc_types.cpp
|
||||
gen-cpp/proc_types.h
|
||||
)
|
||||
add_library(testgencpp_cob STATIC ${testgencpp_cob_SOURCES})
|
||||
|
||||
|
||||
add_executable(Benchmark Benchmark.cpp)
|
||||
target_link_libraries(Benchmark testgencpp)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(Benchmark thrift)
|
||||
add_test(NAME Benchmark COMMAND Benchmark)
|
||||
target_link_libraries(Benchmark testgencpp)
|
||||
|
||||
set(UnitTest_SOURCES
|
||||
UnitTestMain.cpp
|
||||
TMemoryBufferTest.cpp
|
||||
TBufferBaseTest.cpp
|
||||
Base64Test.cpp
|
||||
ToStringTest.cpp
|
||||
TypedefTest.cpp
|
||||
TServerSocketTest.cpp
|
||||
TServerTransportTest.cpp
|
||||
)
|
||||
|
||||
if(NOT WITH_BOOSTTHREADS AND NOT WITH_STDTHREADS AND NOT MSVC)
|
||||
list(APPEND UnitTest_SOURCES RWMutexStarveTest.cpp)
|
||||
endif()
|
||||
|
||||
add_executable(UnitTests ${UnitTest_SOURCES})
|
||||
target_link_libraries(UnitTests testgencpp ${Boost_LIBRARIES})
|
||||
LINK_AGAINST_THRIFT_LIBRARY(UnitTests thrift)
|
||||
add_test(NAME UnitTests COMMAND UnitTests)
|
||||
if ( MSVC )
|
||||
# Disable C4503: decorated name length exceeded, name was truncated
|
||||
# 'insanity' results in very long decorated names
|
||||
set_property( TARGET UnitTests APPEND_STRING PROPERTY COMPILE_FLAGS /wd4503 )
|
||||
endif ( MSVC )
|
||||
|
||||
|
||||
set( TInterruptTest_SOURCES
|
||||
TSocketInterruptTest.cpp
|
||||
TSSLSocketInterruptTest.cpp
|
||||
)
|
||||
if (WIN32)
|
||||
list(APPEND TInterruptTest_SOURCES
|
||||
TPipeInterruptTest.cpp
|
||||
)
|
||||
endif()
|
||||
add_executable(TInterruptTest ${TInterruptTest_SOURCES})
|
||||
target_link_libraries(TInterruptTest
|
||||
testgencpp
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(TInterruptTest thrift)
|
||||
if (NOT MSVC AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT MINGW)
|
||||
target_link_libraries(TInterruptTest -lrt)
|
||||
endif ()
|
||||
add_test(NAME TInterruptTest COMMAND TInterruptTest "${CMAKE_CURRENT_SOURCE_DIR}/../../../test/keys")
|
||||
|
||||
add_executable(TServerIntegrationTest TServerIntegrationTest.cpp)
|
||||
target_link_libraries(TServerIntegrationTest
|
||||
testgencpp_cob
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(TServerIntegrationTest thrift)
|
||||
if (NOT MSVC AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT MINGW)
|
||||
target_link_libraries(TServerIntegrationTest -lrt)
|
||||
endif ()
|
||||
add_test(NAME TServerIntegrationTest COMMAND TServerIntegrationTest)
|
||||
|
||||
if(WITH_ZLIB)
|
||||
include_directories(SYSTEM "${ZLIB_INCLUDE_DIRS}")
|
||||
add_executable(TransportTest TransportTest.cpp)
|
||||
target_link_libraries(TransportTest
|
||||
testgencpp
|
||||
${Boost_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(TransportTest thrift)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(TransportTest thriftz)
|
||||
add_test(NAME TransportTest COMMAND TransportTest)
|
||||
|
||||
add_executable(ZlibTest ZlibTest.cpp)
|
||||
target_link_libraries(ZlibTest
|
||||
testgencpp
|
||||
${Boost_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(ZlibTest thrift)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(ZlibTest thriftz)
|
||||
add_test(NAME ZlibTest COMMAND ZlibTest)
|
||||
endif(WITH_ZLIB)
|
||||
|
||||
|
||||
add_executable(EnumTest EnumTest.cpp)
|
||||
target_link_libraries(EnumTest
|
||||
testgencpp
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(EnumTest thrift)
|
||||
add_test(NAME EnumTest COMMAND EnumTest)
|
||||
|
||||
if(HAVE_GETOPT_H)
|
||||
add_executable(TFileTransportTest TFileTransportTest.cpp)
|
||||
target_link_libraries(TFileTransportTest
|
||||
testgencpp
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(TFileTransportTest thrift)
|
||||
add_test(NAME TFileTransportTest COMMAND TFileTransportTest)
|
||||
endif()
|
||||
|
||||
add_executable(TFDTransportTest TFDTransportTest.cpp)
|
||||
target_link_libraries(TFDTransportTest
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(TFDTransportTest thrift)
|
||||
add_test(NAME TFDTransportTest COMMAND TFDTransportTest)
|
||||
|
||||
add_executable(TPipedTransportTest TPipedTransportTest.cpp)
|
||||
target_link_libraries(TPipedTransportTest
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(TPipedTransportTest thrift)
|
||||
add_test(NAME TPipedTransportTest COMMAND TPipedTransportTest)
|
||||
|
||||
set(AllProtocolsTest_SOURCES
|
||||
AllProtocolTests.cpp
|
||||
AllProtocolTests.tcc
|
||||
GenericHelpers
|
||||
)
|
||||
|
||||
add_executable(AllProtocolsTest ${AllProtocolsTest_SOURCES})
|
||||
target_link_libraries(AllProtocolsTest
|
||||
testgencpp
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(AllProtocolsTest thrift)
|
||||
add_test(NAME AllProtocolsTest COMMAND AllProtocolsTest)
|
||||
|
||||
# The debug run-time in Windows asserts on isprint() with negative inputs
|
||||
if (NOT MSVC OR (MSVC AND CMAKE_BUILD_TYPE EQUAL "DEBUG"))
|
||||
add_executable(DebugProtoTest DebugProtoTest.cpp)
|
||||
target_link_libraries(DebugProtoTest
|
||||
testgencpp
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(DebugProtoTest thrift)
|
||||
add_test(NAME DebugProtoTest COMMAND DebugProtoTest)
|
||||
endif()
|
||||
|
||||
add_executable(JSONProtoTest JSONProtoTest.cpp)
|
||||
target_link_libraries(JSONProtoTest
|
||||
testgencpp
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(JSONProtoTest thrift)
|
||||
add_test(NAME JSONProtoTest COMMAND JSONProtoTest)
|
||||
|
||||
add_executable(OptionalRequiredTest OptionalRequiredTest.cpp)
|
||||
target_link_libraries(OptionalRequiredTest
|
||||
testgencpp
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(OptionalRequiredTest thrift)
|
||||
add_test(NAME OptionalRequiredTest COMMAND OptionalRequiredTest)
|
||||
|
||||
add_executable(RecursiveTest RecursiveTest.cpp)
|
||||
target_link_libraries(RecursiveTest
|
||||
testgencpp
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(RecursiveTest thrift)
|
||||
add_test(NAME RecursiveTest COMMAND RecursiveTest)
|
||||
|
||||
add_executable(SpecializationTest SpecializationTest.cpp)
|
||||
target_link_libraries(SpecializationTest
|
||||
testgencpp
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(SpecializationTest thrift)
|
||||
add_test(NAME SpecializationTest COMMAND SpecializationTest)
|
||||
|
||||
set(concurrency_test_SOURCES
|
||||
concurrency/Tests.cpp
|
||||
concurrency/ThreadFactoryTests.h
|
||||
concurrency/ThreadManagerTests.h
|
||||
concurrency/TimerManagerTests.h
|
||||
)
|
||||
add_executable(concurrency_test ${concurrency_test_SOURCES})
|
||||
LINK_AGAINST_THRIFT_LIBRARY(concurrency_test thrift)
|
||||
add_test(NAME concurrency_test COMMAND concurrency_test)
|
||||
|
||||
set(link_test_SOURCES
|
||||
link/LinkTest.cpp
|
||||
gen-cpp/ParentService.h
|
||||
link/TemplatedService1.cpp
|
||||
link/TemplatedService2.cpp
|
||||
)
|
||||
|
||||
add_executable(link_test ${link_test_SOURCES})
|
||||
target_link_libraries(link_test testgencpp_cob)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(link_test thrift)
|
||||
target_link_libraries(link_test testgencpp)
|
||||
add_test(NAME link_test COMMAND link_test)
|
||||
|
||||
if(WITH_LIBEVENT)
|
||||
set(processor_test_SOURCES
|
||||
processor/ProcessorTest.cpp
|
||||
processor/EventLog.cpp
|
||||
processor/ServerThread.cpp
|
||||
processor/EventLog.h
|
||||
processor/Handlers.h
|
||||
processor/ServerThread.h
|
||||
)
|
||||
add_executable(processor_test ${processor_test_SOURCES})
|
||||
target_link_libraries(processor_test
|
||||
testgencpp_cob
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(processor_test thrift)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(processor_test thriftnb)
|
||||
add_test(NAME processor_test COMMAND processor_test)
|
||||
|
||||
set(TNonblockingServerTest_SOURCES TNonblockingServerTest.cpp)
|
||||
add_executable(TNonblockingServerTest ${TNonblockingServerTest_SOURCES})
|
||||
include_directories(${LIBEVENT_INCLUDE_DIRS})
|
||||
target_link_libraries(TNonblockingServerTest
|
||||
testgencpp_cob
|
||||
${LIBEVENT_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(TNonblockingServerTest thrift)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(TNonblockingServerTest thriftnb)
|
||||
add_test(NAME TNonblockingServerTest COMMAND TNonblockingServerTest)
|
||||
endif()
|
||||
|
||||
if(OPENSSL_FOUND AND WITH_OPENSSL)
|
||||
add_executable(OpenSSLManualInitTest OpenSSLManualInitTest.cpp)
|
||||
target_link_libraries(OpenSSLManualInitTest
|
||||
${OPENSSL_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(OpenSSLManualInitTest thrift)
|
||||
add_test(NAME OpenSSLManualInitTest COMMAND OpenSSLManualInitTest)
|
||||
|
||||
add_executable(SecurityTest SecurityTest.cpp)
|
||||
target_link_libraries(SecurityTest
|
||||
testgencpp
|
||||
${Boost_LIBRARIES}
|
||||
)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(SecurityTest thrift)
|
||||
if (NOT MSVC AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT MINGW)
|
||||
target_link_libraries(SecurityTest -lrt)
|
||||
endif ()
|
||||
add_test(NAME SecurityTest COMMAND SecurityTest "${CMAKE_CURRENT_SOURCE_DIR}/../../../test/keys")
|
||||
|
||||
endif()
|
||||
|
||||
if(WITH_QT4)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
find_package(Qt4 REQUIRED COMPONENTS QtTest)
|
||||
set(TQTcpServerTest_SOURCES
|
||||
qt/TQTcpServerTest.cpp
|
||||
)
|
||||
add_executable(TQTcpServerTest ${TQTcpServerTest_SOURCES})
|
||||
target_link_libraries(TQTcpServerTest testgencpp_cob thriftqt Qt4::QtTest)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(TQTcpServerTest thrift)
|
||||
add_test(NAME TQTcpServerTest COMMAND TQTcpServerTest)
|
||||
endif()
|
||||
|
||||
if(WITH_QT5)
|
||||
add_subdirectory(qt)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Common thrift code generation rules
|
||||
#
|
||||
|
||||
|
||||
add_custom_command(OUTPUT gen-cpp/DebugProtoTest_types.cpp gen-cpp/DebugProtoTest_types.h gen-cpp/EmptyService.cpp gen-cpp/EmptyService.h
|
||||
COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/DebugProtoTest.thrift
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT gen-cpp/EnumTest_types.cpp gen-cpp/EnumTest_types.h
|
||||
COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/EnumTest.thrift
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT gen-cpp/TypedefTest_types.cpp gen-cpp/TypedefTest_types.h
|
||||
COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/TypedefTest.thrift
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT gen-cpp/OptionalRequiredTest_types.cpp gen-cpp/OptionalRequiredTest_types.h
|
||||
COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/OptionalRequiredTest.thrift
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT gen-cpp/Recursive_types.cpp gen-cpp/Recursive_types.h
|
||||
COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/Recursive.thrift
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT gen-cpp/Service.cpp gen-cpp/StressTest_types.cpp
|
||||
COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/StressTest.thrift
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT gen-cpp/SecondService.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_types.h
|
||||
COMMAND ${THRIFT_COMPILER} --gen cpp ${PROJECT_SOURCE_DIR}/test/ThriftTest.thrift
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT gen-cpp/ChildService.cpp gen-cpp/ChildService.h gen-cpp/ParentService.cpp gen-cpp/ParentService.h gen-cpp/proc_types.cpp gen-cpp/proc_types.h
|
||||
COMMAND ${THRIFT_COMPILER} --gen cpp:templates,cob_style ${CMAKE_CURRENT_SOURCE_DIR}/processor/proc.thrift
|
||||
)
|
309
vendor/git.apache.org/thrift.git/lib/cpp/test/DebugProtoTest.cpp
generated
vendored
Normal file
309
vendor/git.apache.org/thrift.git/lib/cpp/test/DebugProtoTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <cmath>
|
||||
#include "gen-cpp/DebugProtoTest_types.h"
|
||||
#include <thrift/protocol/TDebugProtocol.h>
|
||||
|
||||
#define BOOST_TEST_MODULE DebugProtoTest
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace thrift::test::debug;
|
||||
|
||||
static std::auto_ptr<OneOfEach> ooe;
|
||||
|
||||
void testCaseSetup_1() {
|
||||
ooe.reset(new OneOfEach);
|
||||
ooe->im_true = true;
|
||||
ooe->im_false = false;
|
||||
ooe->a_bite = 0x7f;
|
||||
ooe->integer16 = 27000;
|
||||
ooe->integer32 = 1 << 24;
|
||||
ooe->integer64 = (uint64_t)6000 * 1000 * 1000;
|
||||
ooe->double_precision = M_PI;
|
||||
ooe->some_characters = "Debug THIS!";
|
||||
ooe->zomg_unicode = "\xd7\n\a\t";
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_debug_proto_1) {
|
||||
testCaseSetup_1();
|
||||
|
||||
const std::string expected_result(
|
||||
"OneOfEach {\n"
|
||||
" 01: im_true (bool) = true,\n"
|
||||
" 02: im_false (bool) = false,\n"
|
||||
" 03: a_bite (byte) = 0x7f,\n"
|
||||
" 04: integer16 (i16) = 27000,\n"
|
||||
" 05: integer32 (i32) = 16777216,\n"
|
||||
" 06: integer64 (i64) = 6000000000,\n"
|
||||
" 07: double_precision (double) = 3.1415926535897931,\n"
|
||||
" 08: some_characters (string) = \"Debug THIS!\",\n"
|
||||
" 09: zomg_unicode (string) = \"\\xd7\\n\\a\\t\",\n"
|
||||
" 10: what_who (bool) = false,\n"
|
||||
" 11: base64 (string) = \"\",\n"
|
||||
" 12: byte_list (list) = list<byte>[3] {\n"
|
||||
" [0] = 0x01,\n"
|
||||
" [1] = 0x02,\n"
|
||||
" [2] = 0x03,\n"
|
||||
" },\n"
|
||||
" 13: i16_list (list) = list<i16>[3] {\n"
|
||||
" [0] = 1,\n"
|
||||
" [1] = 2,\n"
|
||||
" [2] = 3,\n"
|
||||
" },\n"
|
||||
" 14: i64_list (list) = list<i64>[3] {\n"
|
||||
" [0] = 1,\n"
|
||||
" [1] = 2,\n"
|
||||
" [2] = 3,\n"
|
||||
" },\n"
|
||||
"}");
|
||||
const std::string result(apache::thrift::ThriftDebugString(*ooe));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
||||
|
||||
static std::auto_ptr<Nesting> n;
|
||||
|
||||
void testCaseSetup_2() {
|
||||
testCaseSetup_1();
|
||||
|
||||
n.reset(new Nesting);
|
||||
n->my_ooe = *ooe;
|
||||
n->my_ooe.integer16 = 16;
|
||||
n->my_ooe.integer32 = 32;
|
||||
n->my_ooe.integer64 = 64;
|
||||
n->my_ooe.double_precision = (std::sqrt(5.0) + 1) / 2;
|
||||
n->my_ooe.some_characters = ":R (me going \"rrrr\")";
|
||||
n->my_ooe.zomg_unicode = "\xd3\x80\xe2\x85\xae\xce\x9d\x20\xd0\x9d\xce"
|
||||
"\xbf\xe2\x85\xbf\xd0\xbe\xc9\xa1\xd0\xb3\xd0"
|
||||
"\xb0\xcf\x81\xe2\x84\x8e\x20\xce\x91\x74\x74"
|
||||
"\xce\xb1\xe2\x85\xbd\xce\xba\xc7\x83\xe2\x80"
|
||||
"\xbc";
|
||||
n->my_bonk.type = 31337;
|
||||
n->my_bonk.message = "I am a bonk... xor!";
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_debug_proto_2) {
|
||||
testCaseSetup_2();
|
||||
|
||||
const std::string expected_result(
|
||||
"Nesting {\n"
|
||||
" 01: my_bonk (struct) = Bonk {\n"
|
||||
" 01: type (i32) = 31337,\n"
|
||||
" 02: message (string) = \"I am a bonk... xor!\",\n"
|
||||
" },\n"
|
||||
" 02: my_ooe (struct) = OneOfEach {\n"
|
||||
" 01: im_true (bool) = true,\n"
|
||||
" 02: im_false (bool) = false,\n"
|
||||
" 03: a_bite (byte) = 0x7f,\n"
|
||||
" 04: integer16 (i16) = 16,\n"
|
||||
" 05: integer32 (i32) = 32,\n"
|
||||
" 06: integer64 (i64) = 64,\n"
|
||||
" 07: double_precision (double) = 1.6180339887498949,\n"
|
||||
" 08: some_characters (string) = \":R (me going \\\"rrrr\\\")\",\n"
|
||||
" 09: zomg_unicode (string) = \"\\xd3\\x80\\xe2\\x85\\xae\\xce\\x9d \\xd"
|
||||
"0\\x9d\\xce\\xbf\\xe2\\x85\\xbf\\xd0\\xbe\\xc9\\xa1\\xd0\\xb3\\xd0\\xb0"
|
||||
"\\xcf\\x81\\xe2\\x84\\x8e \\xce\\x91tt\\xce\\xb1\\xe2\\x85\\xbd\\xce\\xb"
|
||||
"a\\xc7\\x83\\xe2\\x80\\xbc\",\n"
|
||||
" 10: what_who (bool) = false,\n"
|
||||
" 11: base64 (string) = \"\",\n"
|
||||
" 12: byte_list (list) = list<byte>[3] {\n"
|
||||
" [0] = 0x01,\n"
|
||||
" [1] = 0x02,\n"
|
||||
" [2] = 0x03,\n"
|
||||
" },\n"
|
||||
" 13: i16_list (list) = list<i16>[3] {\n"
|
||||
" [0] = 1,\n"
|
||||
" [1] = 2,\n"
|
||||
" [2] = 3,\n"
|
||||
" },\n"
|
||||
" 14: i64_list (list) = list<i64>[3] {\n"
|
||||
" [0] = 1,\n"
|
||||
" [1] = 2,\n"
|
||||
" [2] = 3,\n"
|
||||
" },\n"
|
||||
" },\n"
|
||||
"}");
|
||||
const std::string result(apache::thrift::ThriftDebugString(*n));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
||||
|
||||
static std::auto_ptr<HolyMoley> hm;
|
||||
|
||||
void testCaseSetup_3() {
|
||||
testCaseSetup_2();
|
||||
|
||||
hm.reset(new HolyMoley);
|
||||
|
||||
hm->big.push_back(*ooe);
|
||||
hm->big.push_back(n->my_ooe);
|
||||
hm->big[0].a_bite = 0x22;
|
||||
hm->big[1].a_bite = 0x33;
|
||||
|
||||
std::vector<std::string> stage1;
|
||||
stage1.push_back("and a one");
|
||||
stage1.push_back("and a two");
|
||||
hm->contain.insert(stage1);
|
||||
stage1.clear();
|
||||
stage1.push_back("then a one, two");
|
||||
stage1.push_back("three!");
|
||||
stage1.push_back("FOUR!!");
|
||||
hm->contain.insert(stage1);
|
||||
stage1.clear();
|
||||
hm->contain.insert(stage1);
|
||||
|
||||
std::vector<Bonk> stage2;
|
||||
hm->bonks["nothing"] = stage2;
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 1;
|
||||
stage2.back().message = "Wait.";
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 2;
|
||||
stage2.back().message = "What?";
|
||||
hm->bonks["something"] = stage2;
|
||||
stage2.clear();
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 3;
|
||||
stage2.back().message = "quoth";
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 4;
|
||||
stage2.back().message = "the raven";
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 5;
|
||||
stage2.back().message = "nevermore";
|
||||
hm->bonks["poe"] = stage2;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_debug_proto_3) {
|
||||
testCaseSetup_3();
|
||||
|
||||
const std::string expected_result(
|
||||
"HolyMoley {\n"
|
||||
" 01: big (list) = list<struct>[2] {\n"
|
||||
" [0] = OneOfEach {\n"
|
||||
" 01: im_true (bool) = true,\n"
|
||||
" 02: im_false (bool) = false,\n"
|
||||
" 03: a_bite (byte) = 0x22,\n"
|
||||
" 04: integer16 (i16) = 27000,\n"
|
||||
" 05: integer32 (i32) = 16777216,\n"
|
||||
" 06: integer64 (i64) = 6000000000,\n"
|
||||
" 07: double_precision (double) = 3.1415926535897931,\n"
|
||||
" 08: some_characters (string) = \"Debug THIS!\",\n"
|
||||
" 09: zomg_unicode (string) = \"\\xd7\\n\\a\\t\",\n"
|
||||
" 10: what_who (bool) = false,\n"
|
||||
" 11: base64 (string) = \"\",\n"
|
||||
" 12: byte_list (list) = list<byte>[3] {\n"
|
||||
" [0] = 0x01,\n"
|
||||
" [1] = 0x02,\n"
|
||||
" [2] = 0x03,\n"
|
||||
" },\n"
|
||||
" 13: i16_list (list) = list<i16>[3] {\n"
|
||||
" [0] = 1,\n"
|
||||
" [1] = 2,\n"
|
||||
" [2] = 3,\n"
|
||||
" },\n"
|
||||
" 14: i64_list (list) = list<i64>[3] {\n"
|
||||
" [0] = 1,\n"
|
||||
" [1] = 2,\n"
|
||||
" [2] = 3,\n"
|
||||
" },\n"
|
||||
" },\n"
|
||||
" [1] = OneOfEach {\n"
|
||||
" 01: im_true (bool) = true,\n"
|
||||
" 02: im_false (bool) = false,\n"
|
||||
" 03: a_bite (byte) = 0x33,\n"
|
||||
" 04: integer16 (i16) = 16,\n"
|
||||
" 05: integer32 (i32) = 32,\n"
|
||||
" 06: integer64 (i64) = 64,\n"
|
||||
" 07: double_precision (double) = 1.6180339887498949,\n"
|
||||
" 08: some_characters (string) = \":R (me going \\\"rrrr\\\")\",\n"
|
||||
" 09: zomg_unicode (string) = \"\\xd3\\x80\\xe2\\x85\\xae\\xce\\x9d \\"
|
||||
"xd0\\x9d\\xce\\xbf\\xe2\\x85\\xbf\\xd0\\xbe\\xc9\\xa1\\xd0\\xb3\\xd0\\xb"
|
||||
"0\\xcf\\x81\\xe2\\x84\\x8e \\xce\\x91tt\\xce\\xb1\\xe2\\x85\\xbd\\xce\\x"
|
||||
"ba\\xc7\\x83\\xe2\\x80\\xbc\",\n"
|
||||
" 10: what_who (bool) = false,\n"
|
||||
" 11: base64 (string) = \"\",\n"
|
||||
" 12: byte_list (list) = list<byte>[3] {\n"
|
||||
" [0] = 0x01,\n"
|
||||
" [1] = 0x02,\n"
|
||||
" [2] = 0x03,\n"
|
||||
" },\n"
|
||||
" 13: i16_list (list) = list<i16>[3] {\n"
|
||||
" [0] = 1,\n"
|
||||
" [1] = 2,\n"
|
||||
" [2] = 3,\n"
|
||||
" },\n"
|
||||
" 14: i64_list (list) = list<i64>[3] {\n"
|
||||
" [0] = 1,\n"
|
||||
" [1] = 2,\n"
|
||||
" [2] = 3,\n"
|
||||
" },\n"
|
||||
" },\n"
|
||||
" },\n"
|
||||
" 02: contain (set) = set<list>[3] {\n"
|
||||
" list<string>[0] {\n"
|
||||
" },\n"
|
||||
" list<string>[2] {\n"
|
||||
" [0] = \"and a one\",\n"
|
||||
" [1] = \"and a two\",\n"
|
||||
" },\n"
|
||||
" list<string>[3] {\n"
|
||||
" [0] = \"then a one, two\",\n"
|
||||
" [1] = \"three!\",\n"
|
||||
" [2] = \"FOUR!!\",\n"
|
||||
" },\n"
|
||||
" },\n"
|
||||
" 03: bonks (map) = map<string,list>[3] {\n"
|
||||
" \"nothing\" -> list<struct>[0] {\n"
|
||||
" },\n"
|
||||
" \"poe\" -> list<struct>[3] {\n"
|
||||
" [0] = Bonk {\n"
|
||||
" 01: type (i32) = 3,\n"
|
||||
" 02: message (string) = \"quoth\",\n"
|
||||
" },\n"
|
||||
" [1] = Bonk {\n"
|
||||
" 01: type (i32) = 4,\n"
|
||||
" 02: message (string) = \"the raven\",\n"
|
||||
" },\n"
|
||||
" [2] = Bonk {\n"
|
||||
" 01: type (i32) = 5,\n"
|
||||
" 02: message (string) = \"nevermore\",\n"
|
||||
" },\n"
|
||||
" },\n"
|
||||
" \"something\" -> list<struct>[2] {\n"
|
||||
" [0] = Bonk {\n"
|
||||
" 01: type (i32) = 1,\n"
|
||||
" 02: message (string) = \"Wait.\",\n"
|
||||
" },\n"
|
||||
" [1] = Bonk {\n"
|
||||
" 01: type (i32) = 2,\n"
|
||||
" 02: message (string) = \"What?\",\n"
|
||||
" },\n"
|
||||
" },\n"
|
||||
" },\n"
|
||||
"}");
|
||||
const std::string result(apache::thrift::ThriftDebugString(*hm));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
35
vendor/git.apache.org/thrift.git/lib/cpp/test/DebugProtoTest_extras.cpp
generated
vendored
Normal file
35
vendor/git.apache.org/thrift.git/lib/cpp/test/DebugProtoTest_extras.cpp
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Extra functions required for DebugProtoTest_types to work
|
||||
|
||||
#include "gen-cpp/DebugProtoTest_types.h"
|
||||
|
||||
namespace thrift {
|
||||
namespace test {
|
||||
namespace debug {
|
||||
|
||||
bool Empty::operator<(Empty const& other) const {
|
||||
(void)other;
|
||||
// It is empty, so all are equal.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
59
vendor/git.apache.org/thrift.git/lib/cpp/test/EnumTest.cpp
generated
vendored
Normal file
59
vendor/git.apache.org/thrift.git/lib/cpp/test/EnumTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#define BOOST_TEST_MODULE EnumTest
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include "gen-cpp/EnumTest_types.h"
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(EnumTest)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_enum) {
|
||||
// Check that all the enum values match what we expect
|
||||
BOOST_CHECK_EQUAL(MyEnum1::ME1_0, 0);
|
||||
BOOST_CHECK_EQUAL(MyEnum1::ME1_1, 1);
|
||||
BOOST_CHECK_EQUAL(MyEnum1::ME1_2, 2);
|
||||
BOOST_CHECK_EQUAL(MyEnum1::ME1_3, 3);
|
||||
BOOST_CHECK_EQUAL(MyEnum1::ME1_5, 5);
|
||||
BOOST_CHECK_EQUAL(MyEnum1::ME1_6, 6);
|
||||
|
||||
BOOST_CHECK_EQUAL(MyEnum2::ME2_0, 0);
|
||||
BOOST_CHECK_EQUAL(MyEnum2::ME2_1, 1);
|
||||
BOOST_CHECK_EQUAL(MyEnum2::ME2_2, 2);
|
||||
|
||||
BOOST_CHECK_EQUAL(MyEnum3::ME3_0, 0);
|
||||
BOOST_CHECK_EQUAL(MyEnum3::ME3_1, 1);
|
||||
BOOST_CHECK_EQUAL(MyEnum3::ME3_N2, -2);
|
||||
BOOST_CHECK_EQUAL(MyEnum3::ME3_N1, -1);
|
||||
BOOST_CHECK_EQUAL(MyEnum3::ME3_D0, 0);
|
||||
BOOST_CHECK_EQUAL(MyEnum3::ME3_D1, 1);
|
||||
BOOST_CHECK_EQUAL(MyEnum3::ME3_9, 9);
|
||||
BOOST_CHECK_EQUAL(MyEnum3::ME3_10, 10);
|
||||
|
||||
BOOST_CHECK_EQUAL(MyEnum4::ME4_A, 0x7ffffffd);
|
||||
BOOST_CHECK_EQUAL(MyEnum4::ME4_B, 0x7ffffffe);
|
||||
BOOST_CHECK_EQUAL(MyEnum4::ME4_C, 0x7fffffff);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_enum_constant) {
|
||||
MyStruct ms;
|
||||
BOOST_CHECK_EQUAL(ms.me2_2, 2);
|
||||
BOOST_CHECK_EQUAL(ms.me3_n2, -2);
|
||||
BOOST_CHECK_EQUAL(ms.me3_d1, 1);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
110
vendor/git.apache.org/thrift.git/lib/cpp/test/GenericHelpers.h
generated
vendored
Normal file
110
vendor/git.apache.org/thrift.git/lib/cpp/test/GenericHelpers.h
generated
vendored
Normal file
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 _THRIFT_TEST_GENERICHELPERS_H_
|
||||
#define _THRIFT_TEST_GENERICHELPERS_H_ 1
|
||||
|
||||
#include <thrift/protocol/TBinaryProtocol.h>
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
#include <thrift/Thrift.h>
|
||||
|
||||
using boost::shared_ptr;
|
||||
using namespace apache::thrift::protocol;
|
||||
|
||||
/* ClassName Helper for cleaner exceptions */
|
||||
class ClassNames {
|
||||
public:
|
||||
template <typename T>
|
||||
static const char* getName() {
|
||||
return "Unknown type";
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
const char* ClassNames::getName<int8_t>() {
|
||||
return "byte";
|
||||
}
|
||||
template <>
|
||||
const char* ClassNames::getName<int16_t>() {
|
||||
return "short";
|
||||
}
|
||||
template <>
|
||||
const char* ClassNames::getName<int32_t>() {
|
||||
return "int";
|
||||
}
|
||||
template <>
|
||||
const char* ClassNames::getName<int64_t>() {
|
||||
return "long";
|
||||
}
|
||||
template <>
|
||||
const char* ClassNames::getName<double>() {
|
||||
return "double";
|
||||
}
|
||||
template <>
|
||||
const char* ClassNames::getName<std::string>() {
|
||||
return "string";
|
||||
}
|
||||
|
||||
/* Generic Protocol I/O function for tests */
|
||||
class GenericIO {
|
||||
public:
|
||||
/* Write functions */
|
||||
|
||||
static uint32_t write(shared_ptr<TProtocol> proto, const int8_t& val) {
|
||||
return proto->writeByte(val);
|
||||
}
|
||||
|
||||
static uint32_t write(shared_ptr<TProtocol> proto, const int16_t& val) {
|
||||
return proto->writeI16(val);
|
||||
}
|
||||
|
||||
static uint32_t write(shared_ptr<TProtocol> proto, const int32_t& val) {
|
||||
return proto->writeI32(val);
|
||||
}
|
||||
|
||||
static uint32_t write(shared_ptr<TProtocol> proto, const double& val) {
|
||||
return proto->writeDouble(val);
|
||||
}
|
||||
|
||||
static uint32_t write(shared_ptr<TProtocol> proto, const int64_t& val) {
|
||||
return proto->writeI64(val);
|
||||
}
|
||||
|
||||
static uint32_t write(shared_ptr<TProtocol> proto, const std::string& val) {
|
||||
return proto->writeString(val);
|
||||
}
|
||||
|
||||
/* Read functions */
|
||||
|
||||
static uint32_t read(shared_ptr<TProtocol> proto, int8_t& val) { return proto->readByte(val); }
|
||||
|
||||
static uint32_t read(shared_ptr<TProtocol> proto, int16_t& val) { return proto->readI16(val); }
|
||||
|
||||
static uint32_t read(shared_ptr<TProtocol> proto, int32_t& val) { return proto->readI32(val); }
|
||||
|
||||
static uint32_t read(shared_ptr<TProtocol> proto, int64_t& val) { return proto->readI64(val); }
|
||||
|
||||
static uint32_t read(shared_ptr<TProtocol> proto, double& val) { return proto->readDouble(val); }
|
||||
|
||||
static uint32_t read(shared_ptr<TProtocol> proto, std::string& val) {
|
||||
return proto->readString(val);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
340
vendor/git.apache.org/thrift.git/lib/cpp/test/JSONProtoTest.cpp
generated
vendored
Normal file
340
vendor/git.apache.org/thrift.git/lib/cpp/test/JSONProtoTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
#include <thrift/protocol/TJSONProtocol.h>
|
||||
#include "gen-cpp/DebugProtoTest_types.h"
|
||||
|
||||
#define BOOST_TEST_MODULE JSONProtoTest
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace thrift::test::debug;
|
||||
using apache::thrift::transport::TMemoryBuffer;
|
||||
using apache::thrift::protocol::TJSONProtocol;
|
||||
|
||||
static std::auto_ptr<OneOfEach> ooe;
|
||||
|
||||
void testCaseSetup_1() {
|
||||
ooe.reset(new OneOfEach);
|
||||
ooe->im_true = true;
|
||||
ooe->im_false = false;
|
||||
ooe->a_bite = 0x7f;
|
||||
ooe->integer16 = 27000;
|
||||
ooe->integer32 = 1 << 24;
|
||||
ooe->integer64 = (uint64_t)6000 * 1000 * 1000;
|
||||
ooe->double_precision = M_PI;
|
||||
ooe->some_characters = "JSON THIS! \"\1";
|
||||
ooe->zomg_unicode = "\xd7\n\a\t";
|
||||
ooe->base64 = "\1\2\3\255";
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_json_proto_1) {
|
||||
testCaseSetup_1();
|
||||
|
||||
const std::string expected_result(
|
||||
"{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000},"
|
||||
"\"5\":{\"i32\":16777216},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926"
|
||||
"535897931},\"8\":{\"str\":\"JSON THIS! \\\"\\u0001\"},\"9\":{\"str\":\"\xd7\\"
|
||||
"n\\u0007\\t\"},\"10\":{\"tf\":0},\"11\":{\"str\":\"AQIDrQ\"},\"12\":{\"lst\""
|
||||
":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64"
|
||||
"\",3,1,2,3]}}");
|
||||
|
||||
const std::string result(apache::thrift::ThriftJSONString(*ooe));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
||||
|
||||
static std::auto_ptr<Nesting> n;
|
||||
|
||||
void testCaseSetup_2() {
|
||||
testCaseSetup_1();
|
||||
|
||||
n.reset(new Nesting);
|
||||
n->my_ooe = *ooe;
|
||||
n->my_ooe.integer16 = 16;
|
||||
n->my_ooe.integer32 = 32;
|
||||
n->my_ooe.integer64 = 64;
|
||||
n->my_ooe.double_precision = (std::sqrt(5.0) + 1) / 2;
|
||||
n->my_ooe.some_characters = ":R (me going \"rrrr\")";
|
||||
n->my_ooe.zomg_unicode = "\xd3\x80\xe2\x85\xae\xce\x9d\x20\xd0\x9d\xce"
|
||||
"\xbf\xe2\x85\xbf\xd0\xbe\xc9\xa1\xd0\xb3\xd0"
|
||||
"\xb0\xcf\x81\xe2\x84\x8e\x20\xce\x91\x74\x74"
|
||||
"\xce\xb1\xe2\x85\xbd\xce\xba\xc7\x83\xe2\x80"
|
||||
"\xbc";
|
||||
n->my_bonk.type = 31337;
|
||||
n->my_bonk.message = "I am a bonk... xor!";
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_json_proto_2) {
|
||||
testCaseSetup_2();
|
||||
|
||||
const std::string expected_result(
|
||||
"{\"1\":{\"rec\":{\"1\":{\"i32\":31337},\"2\":{\"str\":\"I am a bonk... xor"
|
||||
"!\"}}},\"2\":{\"rec\":{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127"
|
||||
"},\"4\":{\"i16\":16},\"5\":{\"i32\":32},\"6\":{\"i64\":64},\"7\":{\"dbl\":"
|
||||
"1.6180339887498949},\"8\":{\"str\":\":R (me going \\\"rrrr\\\")\"},\"9\":{"
|
||||
"\"str\":\"ӀⅮΝ Нοⅿоɡгаρℎ Αttαⅽκǃ‼\"},\"10\":{\"tf\":0},\"11\":{\"str\":\""
|
||||
"AQIDrQ\"},\"12\":{\"lst\":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2"
|
||||
",3]},\"14\":{\"lst\":[\"i64\",3,1,2,3]}}}}"
|
||||
);
|
||||
|
||||
const std::string result(apache::thrift::ThriftJSONString(*n));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
||||
|
||||
static std::auto_ptr<HolyMoley> hm;
|
||||
|
||||
void testCaseSetup_3() {
|
||||
testCaseSetup_2();
|
||||
|
||||
hm.reset(new HolyMoley);
|
||||
|
||||
hm->big.push_back(*ooe);
|
||||
hm->big.push_back(n->my_ooe);
|
||||
hm->big[0].a_bite = 0x22;
|
||||
hm->big[1].a_bite = 0x33;
|
||||
|
||||
std::vector<std::string> stage1;
|
||||
stage1.push_back("and a one");
|
||||
stage1.push_back("and a two");
|
||||
hm->contain.insert(stage1);
|
||||
stage1.clear();
|
||||
stage1.push_back("then a one, two");
|
||||
stage1.push_back("three!");
|
||||
stage1.push_back("FOUR!!");
|
||||
hm->contain.insert(stage1);
|
||||
stage1.clear();
|
||||
hm->contain.insert(stage1);
|
||||
|
||||
std::vector<Bonk> stage2;
|
||||
hm->bonks["nothing"] = stage2;
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 1;
|
||||
stage2.back().message = "Wait.";
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 2;
|
||||
stage2.back().message = "What?";
|
||||
hm->bonks["something"] = stage2;
|
||||
stage2.clear();
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 3;
|
||||
stage2.back().message = "quoth";
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 4;
|
||||
stage2.back().message = "the raven";
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 5;
|
||||
stage2.back().message = "nevermore";
|
||||
hm->bonks["poe"] = stage2;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_json_proto_3) {
|
||||
testCaseSetup_3();
|
||||
|
||||
const std::string expected_result(
|
||||
"{\"1\":{\"lst\":[\"rec\",2,{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":"
|
||||
"34},\"4\":{\"i16\":27000},\"5\":{\"i32\":16777216},\"6\":{\"i64\":6000000000"
|
||||
"},\"7\":{\"dbl\":3.1415926535897931},\"8\":{\"str\":\"JSON THIS! \\\"\\u0001"
|
||||
"\"},\"9\":{\"str\":\"\xd7\\n\\u0007\\t\"},\"10\":{\"tf\":0},\"11\":{\"str\":"
|
||||
"\"AQIDrQ\"},\"12\":{\"lst\":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2"
|
||||
",3]},\"14\":{\"lst\":[\"i64\",3,1,2,3]}},{\"1\":{\"tf\":1},\"2\":{\"tf\":0},"
|
||||
"\"3\":{\"i8\":51},\"4\":{\"i16\":16},\"5\":{\"i32\":32},\"6\":{\"i64\":64},"
|
||||
"\"7\":{\"dbl\":1.6180339887498949},\"8\":{\"str\":\":R (me going \\\"rrrr\\\""
|
||||
")\"},\"9\":{\"str\":\"ӀⅮΝ Нοⅿоɡгаρℎ Αttαⅽκǃ‼\"},\"10\":{\"tf\":0},\"11\":{"
|
||||
"\"str\":\"AQIDrQ\"},\"12\":{\"lst\":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16"
|
||||
"\",3,1,2,3]},\"14\":{\"lst\":[\"i64\",3,1,2,3]}}]},\"2\":{\"set\":[\"lst\",3"
|
||||
",[\"str\",0],[\"str\",2,\"and a one\",\"and a two\"],[\"str\",3,\"then a one"
|
||||
", two\",\"three!\",\"FOUR!!\"]]},\"3\":{\"map\":[\"str\",\"lst\",3,{\"nothin"
|
||||
"g\":[\"rec\",0],\"poe\":[\"rec\",3,{\"1\":{\"i32\":3},\"2\":{\"str\":\"quoth"
|
||||
"\"}},{\"1\":{\"i32\":4},\"2\":{\"str\":\"the raven\"}},{\"1\":{\"i32\":5},\""
|
||||
"2\":{\"str\":\"nevermore\"}}],\"something\":[\"rec\",2,{\"1\":{\"i32\":1},\""
|
||||
"2\":{\"str\":\"Wait.\"}},{\"1\":{\"i32\":2},\"2\":{\"str\":\"What?\"}}]}]}}"
|
||||
);
|
||||
|
||||
const std::string result(apache::thrift::ThriftJSONString(*hm));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_json_proto_4) {
|
||||
testCaseSetup_1();
|
||||
|
||||
boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
|
||||
boost::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
|
||||
|
||||
ooe->write(proto.get());
|
||||
OneOfEach ooe2;
|
||||
ooe2.read(proto.get());
|
||||
|
||||
BOOST_CHECK(*ooe == ooe2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_json_proto_5) {
|
||||
testCaseSetup_3();
|
||||
|
||||
boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
|
||||
boost::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
|
||||
|
||||
hm->write(proto.get());
|
||||
HolyMoley hm2;
|
||||
hm2.read(proto.get());
|
||||
|
||||
BOOST_CHECK(*hm == hm2);
|
||||
|
||||
hm2.big[0].a_bite = 0x00;
|
||||
|
||||
BOOST_CHECK(*hm != hm2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_json_proto_6) {
|
||||
Doubles dub;
|
||||
dub.nan = HUGE_VAL / HUGE_VAL;
|
||||
dub.inf = HUGE_VAL;
|
||||
dub.neginf = -HUGE_VAL;
|
||||
dub.repeating = 10.0 / 3.0;
|
||||
dub.big = 1E+305;
|
||||
dub.tiny = 1E-305;
|
||||
dub.zero = 0.0;
|
||||
dub.negzero = -0.0;
|
||||
|
||||
const std::string expected_result(
|
||||
"{\"1\":{\"dbl\":\"NaN\"},\"2\":{\"dbl\":\"Infinity\"},\"3\":{\"dbl\":\"-Infi"
|
||||
"nity\"},\"4\":{\"dbl\":3.3333333333333335},\"5\":{\"dbl\":9.9999999999999994e+"
|
||||
"304},\"6\":{\"dbl\":1e-305},\"7\":{\"dbl\":0},\"8\":{\"dbl\":-0}}"
|
||||
);
|
||||
|
||||
const std::string result(apache::thrift::ThriftJSONString(dub));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_json_proto_7) {
|
||||
boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
|
||||
boost::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
|
||||
|
||||
Base64 base;
|
||||
base.a = 123;
|
||||
base.b1 = "1";
|
||||
base.b2 = "12";
|
||||
base.b3 = "123";
|
||||
base.b4 = "1234";
|
||||
base.b5 = "12345";
|
||||
base.b6 = "123456";
|
||||
|
||||
base.write(proto.get());
|
||||
Base64 base2;
|
||||
base2.read(proto.get());
|
||||
|
||||
BOOST_CHECK(base == base2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_json_proto_8) {
|
||||
const char* json_string =
|
||||
"{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000},"
|
||||
"\"5\":{\"i32\":16.77216},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926"
|
||||
"535897931},\"8\":{\"str\":\"JSON THIS! \\\"\\u0001\"},\"9\":{\"str\":\"\xd7\\"
|
||||
"n\\u0007\\t\"},\"10\":{\"tf\":0},\"11\":{\"str\":\"AQIDrQ\"},\"12\":{\"lst\""
|
||||
":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64"
|
||||
"\",3,1,2,3]}}";
|
||||
|
||||
boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
|
||||
(uint8_t*)(json_string), strlen(json_string)*sizeof(char)));
|
||||
boost::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
|
||||
|
||||
OneOfEach ooe2;
|
||||
|
||||
BOOST_CHECK_THROW(ooe2.read(proto.get()),
|
||||
apache::thrift::protocol::TProtocolException);
|
||||
}
|
||||
|
||||
static std::string toHexSequence(const std::string& str) {
|
||||
std::stringstream ss;
|
||||
ss << std::hex << std::setfill('0');
|
||||
for (std::size_t i = 0; i < str.size(); i++) {
|
||||
ss << "\\x" << int(uint8_t(str[i]));
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_json_unicode_escaped) {
|
||||
const char json_string[] =
|
||||
"{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000},"
|
||||
"\"5\":{\"i32\":16},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926"
|
||||
"535897931},\"8\":{\"str\":\"JSON THIS!\"},\"9\":{\"str\":\"\\u0e01 \\ud835\\udd3e\"},"
|
||||
"\"10\":{\"tf\":0},\"11\":{\"str\":\"000000\"},\"12\":{\"lst\""
|
||||
":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64"
|
||||
"\",3,1,2,3]}}";
|
||||
const char* expected_zomg_unicode = "\xe0\xb8\x81 \xf0\x9d\x94\xbe";
|
||||
|
||||
boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
|
||||
(uint8_t*)(json_string), sizeof(json_string)));
|
||||
boost::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
|
||||
|
||||
OneOfEach ooe2;
|
||||
ooe2.read(proto.get());
|
||||
BOOST_CHECK_MESSAGE(!ooe2.zomg_unicode.compare(expected_zomg_unicode),
|
||||
"Expected:\n" << toHexSequence(expected_zomg_unicode) << "\nGotten:\n"
|
||||
<< toHexSequence(ooe2.zomg_unicode));
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_json_unicode_escaped_missing_low_surrogate) {
|
||||
const char json_string[] =
|
||||
"{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000},"
|
||||
"\"5\":{\"i32\":16},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926"
|
||||
"535897931},\"8\":{\"str\":\"JSON THIS!\"},\"9\":{\"str\":\"\\ud835\"},"
|
||||
"\"10\":{\"tf\":0},\"11\":{\"str\":\"000000\"},\"12\":{\"lst\""
|
||||
":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64"
|
||||
"\",3,1,2,3]}}";
|
||||
|
||||
boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
|
||||
(uint8_t*)(json_string), sizeof(json_string)));
|
||||
boost::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
|
||||
|
||||
OneOfEach ooe2;
|
||||
BOOST_CHECK_THROW(ooe2.read(proto.get()),
|
||||
apache::thrift::protocol::TProtocolException);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_json_unicode_escaped_missing_hi_surrogate) {
|
||||
const char json_string[] =
|
||||
"{\"1\":{\"tf\":1},\"2\":{\"tf\":0},\"3\":{\"i8\":127},\"4\":{\"i16\":27000},"
|
||||
"\"5\":{\"i32\":16},\"6\":{\"i64\":6000000000},\"7\":{\"dbl\":3.1415926"
|
||||
"535897931},\"8\":{\"str\":\"JSON THIS!\"},\"9\":{\"str\":\"\\udd3e\"},"
|
||||
"\"10\":{\"tf\":0},\"11\":{\"str\":\"000000\"},\"12\":{\"lst\""
|
||||
":[\"i8\",3,1,2,3]},\"13\":{\"lst\":[\"i16\",3,1,2,3]},\"14\":{\"lst\":[\"i64"
|
||||
"\",3,1,2,3]}}";
|
||||
|
||||
boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
|
||||
(uint8_t*)(json_string), sizeof(json_string)));
|
||||
boost::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
|
||||
|
||||
OneOfEach ooe2;
|
||||
BOOST_CHECK_THROW(ooe2.read(proto.get()),
|
||||
apache::thrift::protocol::TProtocolException);
|
||||
}
|
374
vendor/git.apache.org/thrift.git/lib/cpp/test/Makefile.am
generated
vendored
Executable file
374
vendor/git.apache.org/thrift.git/lib/cpp/test/Makefile.am
generated
vendored
Executable file
|
@ -0,0 +1,374 @@
|
|||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
AUTOMAKE_OPTIONS = subdir-objects serial-tests
|
||||
|
||||
BUILT_SOURCES = gen-cpp/DebugProtoTest_types.h \
|
||||
gen-cpp/EnumTest_types.h \
|
||||
gen-cpp/OptionalRequiredTest_types.h \
|
||||
gen-cpp/Recursive_types.h \
|
||||
gen-cpp/ThriftTest_types.h \
|
||||
gen-cpp/TypedefTest_types.h \
|
||||
gen-cpp/ChildService.h \
|
||||
gen-cpp/EmptyService.h \
|
||||
gen-cpp/ParentService.h \
|
||||
gen-cpp/proc_types.h
|
||||
|
||||
noinst_LTLIBRARIES = libtestgencpp.la libprocessortest.la
|
||||
nodist_libtestgencpp_la_SOURCES = \
|
||||
gen-cpp/DebugProtoTest_types.cpp \
|
||||
gen-cpp/DebugProtoTest_types.h \
|
||||
gen-cpp/EnumTest_types.cpp \
|
||||
gen-cpp/EnumTest_types.h \
|
||||
gen-cpp/OptionalRequiredTest_types.cpp \
|
||||
gen-cpp/OptionalRequiredTest_types.h \
|
||||
gen-cpp/Recursive_types.cpp \
|
||||
gen-cpp/Recursive_types.h \
|
||||
gen-cpp/ThriftTest_types.cpp \
|
||||
gen-cpp/ThriftTest_types.h \
|
||||
gen-cpp/ThriftTest_constants.cpp \
|
||||
gen-cpp/ThriftTest_constants.h \
|
||||
gen-cpp/TypedefTest_types.cpp \
|
||||
gen-cpp/TypedefTest_types.h \
|
||||
ThriftTest_extras.cpp \
|
||||
DebugProtoTest_extras.cpp
|
||||
|
||||
nodist_libprocessortest_la_SOURCES = \
|
||||
gen-cpp/ChildService.cpp \
|
||||
gen-cpp/ChildService.h \
|
||||
gen-cpp/EmptyService.cpp \
|
||||
gen-cpp/EmptyService.h \
|
||||
gen-cpp/ParentService.cpp \
|
||||
gen-cpp/ParentService.h \
|
||||
gen-cpp/proc_types.cpp \
|
||||
gen-cpp/proc_types.h
|
||||
|
||||
ThriftTest_extras.o: gen-cpp/ThriftTest_types.h
|
||||
DebugProtoTest_extras.o: gen-cpp/DebugProtoTest_types.h
|
||||
|
||||
libtestgencpp_la_LIBADD = $(top_builddir)/lib/cpp/libthrift.la
|
||||
|
||||
noinst_PROGRAMS = Benchmark \
|
||||
concurrency_test
|
||||
|
||||
Benchmark_SOURCES = \
|
||||
Benchmark.cpp
|
||||
|
||||
Benchmark_LDADD = libtestgencpp.la
|
||||
|
||||
check_PROGRAMS = \
|
||||
UnitTests \
|
||||
TFDTransportTest \
|
||||
TPipedTransportTest \
|
||||
DebugProtoTest \
|
||||
JSONProtoTest \
|
||||
OptionalRequiredTest \
|
||||
RecursiveTest \
|
||||
SpecializationTest \
|
||||
AllProtocolsTest \
|
||||
TransportTest \
|
||||
TInterruptTest \
|
||||
TServerIntegrationTest \
|
||||
SecurityTest \
|
||||
ZlibTest \
|
||||
TFileTransportTest \
|
||||
link_test \
|
||||
OpenSSLManualInitTest \
|
||||
EnumTest
|
||||
|
||||
if AMX_HAVE_LIBEVENT
|
||||
noinst_PROGRAMS += \
|
||||
processor_test
|
||||
check_PROGRAMS += \
|
||||
TNonblockingServerTest
|
||||
endif
|
||||
|
||||
TESTS_ENVIRONMENT= \
|
||||
BOOST_TEST_LOG_SINK=tests.xml \
|
||||
BOOST_TEST_LOG_LEVEL=test_suite \
|
||||
BOOST_TEST_LOG_FORMAT=XML
|
||||
|
||||
TESTS = \
|
||||
$(check_PROGRAMS)
|
||||
|
||||
UnitTests_SOURCES = \
|
||||
UnitTestMain.cpp \
|
||||
TMemoryBufferTest.cpp \
|
||||
TBufferBaseTest.cpp \
|
||||
Base64Test.cpp \
|
||||
ToStringTest.cpp \
|
||||
TypedefTest.cpp \
|
||||
TServerSocketTest.cpp \
|
||||
TServerTransportTest.cpp \
|
||||
TTransportCheckThrow.h
|
||||
|
||||
if !WITH_BOOSTTHREADS
|
||||
UnitTests_SOURCES += \
|
||||
RWMutexStarveTest.cpp
|
||||
endif
|
||||
|
||||
UnitTests_LDADD = \
|
||||
libtestgencpp.la \
|
||||
$(BOOST_TEST_LDADD)
|
||||
|
||||
TInterruptTest_SOURCES = \
|
||||
TSocketInterruptTest.cpp \
|
||||
TSSLSocketInterruptTest.cpp
|
||||
|
||||
TInterruptTest_LDADD = \
|
||||
libtestgencpp.la \
|
||||
$(BOOST_TEST_LDADD) \
|
||||
$(BOOST_FILESYSTEM_LDADD) \
|
||||
$(BOOST_CHRONO_LDADD) \
|
||||
$(BOOST_SYSTEM_LDADD) \
|
||||
$(BOOST_THREAD_LDADD)
|
||||
|
||||
TServerIntegrationTest_SOURCES = \
|
||||
TServerIntegrationTest.cpp
|
||||
|
||||
TServerIntegrationTest_LDADD = \
|
||||
libtestgencpp.la \
|
||||
libprocessortest.la \
|
||||
$(BOOST_TEST_LDADD) \
|
||||
$(BOOST_SYSTEM_LDADD) \
|
||||
$(BOOST_THREAD_LDADD)
|
||||
|
||||
SecurityTest_SOURCES = \
|
||||
SecurityTest.cpp
|
||||
|
||||
SecurityTest_LDADD = \
|
||||
libtestgencpp.la \
|
||||
libprocessortest.la \
|
||||
$(BOOST_TEST_LDADD) \
|
||||
$(BOOST_FILESYSTEM_LDADD) \
|
||||
$(BOOST_SYSTEM_LDADD) \
|
||||
$(BOOST_THREAD_LDADD)
|
||||
|
||||
TransportTest_SOURCES = \
|
||||
TransportTest.cpp
|
||||
|
||||
TransportTest_LDADD = \
|
||||
libtestgencpp.la \
|
||||
$(top_builddir)/lib/cpp/libthriftz.la \
|
||||
$(BOOST_TEST_LDADD) \
|
||||
-lz
|
||||
|
||||
ZlibTest_SOURCES = \
|
||||
ZlibTest.cpp
|
||||
|
||||
ZlibTest_LDADD = \
|
||||
libtestgencpp.la \
|
||||
$(top_builddir)/lib/cpp/libthriftz.la \
|
||||
$(BOOST_TEST_LDADD) \
|
||||
-lz
|
||||
|
||||
EnumTest_SOURCES = \
|
||||
EnumTest.cpp
|
||||
|
||||
EnumTest_LDADD = \
|
||||
libtestgencpp.la \
|
||||
$(BOOST_TEST_LDADD)
|
||||
|
||||
TFileTransportTest_SOURCES = \
|
||||
TFileTransportTest.cpp
|
||||
|
||||
TFileTransportTest_LDADD = \
|
||||
libtestgencpp.la \
|
||||
$(BOOST_TEST_LDADD)
|
||||
|
||||
#
|
||||
# TFDTransportTest
|
||||
#
|
||||
TFDTransportTest_SOURCES = \
|
||||
TFDTransportTest.cpp
|
||||
|
||||
TFDTransportTest_LDADD = \
|
||||
$(top_builddir)/lib/cpp/libthrift.la \
|
||||
$(BOOST_TEST_LDADD)
|
||||
|
||||
|
||||
#
|
||||
# TPipedTransportTest
|
||||
#
|
||||
TPipedTransportTest_SOURCES = \
|
||||
TPipedTransportTest.cpp \
|
||||
TPipeInterruptTest.cpp
|
||||
|
||||
TPipedTransportTest_LDADD = \
|
||||
libtestgencpp.la \
|
||||
$(top_builddir)/lib/cpp/libthrift.la \
|
||||
$(BOOST_TEST_LDADD) \
|
||||
$(BOOST_SYSTEM_LDADD) \
|
||||
$(BOOST_THREAD_LDADD)
|
||||
|
||||
#
|
||||
# AllProtocolsTest
|
||||
#
|
||||
AllProtocolsTest_SOURCES = \
|
||||
AllProtocolTests.cpp \
|
||||
AllProtocolTests.tcc \
|
||||
GenericHelpers.h
|
||||
|
||||
AllProtocolsTest_LDADD = \
|
||||
libtestgencpp.la \
|
||||
$(BOOST_TEST_LDADD)
|
||||
|
||||
#
|
||||
# DebugProtoTest
|
||||
#
|
||||
DebugProtoTest_SOURCES = \
|
||||
DebugProtoTest.cpp
|
||||
|
||||
DebugProtoTest_LDADD = \
|
||||
libtestgencpp.la \
|
||||
$(BOOST_TEST_LDADD)
|
||||
|
||||
|
||||
#
|
||||
# JSONProtoTest
|
||||
#
|
||||
JSONProtoTest_SOURCES = \
|
||||
JSONProtoTest.cpp
|
||||
|
||||
JSONProtoTest_LDADD = \
|
||||
libtestgencpp.la \
|
||||
$(BOOST_TEST_LDADD)
|
||||
|
||||
#
|
||||
# TNonblockingServerTest
|
||||
#
|
||||
TNonblockingServerTest_SOURCES = TNonblockingServerTest.cpp
|
||||
|
||||
TNonblockingServerTest_LDADD = libprocessortest.la \
|
||||
$(top_builddir)/lib/cpp/libthrift.la \
|
||||
$(top_builddir)/lib/cpp/libthriftnb.la \
|
||||
$(BOOST_TEST_LDADD) \
|
||||
$(BOOST_LDFLAGS) \
|
||||
$(LIBEVENT_LIBS)
|
||||
|
||||
#
|
||||
# OptionalRequiredTest
|
||||
#
|
||||
OptionalRequiredTest_SOURCES = \
|
||||
OptionalRequiredTest.cpp
|
||||
|
||||
OptionalRequiredTest_LDADD = \
|
||||
libtestgencpp.la \
|
||||
$(BOOST_TEST_LDADD)
|
||||
|
||||
#
|
||||
# OptionalRequiredTest
|
||||
#
|
||||
RecursiveTest_SOURCES = \
|
||||
RecursiveTest.cpp
|
||||
|
||||
RecursiveTest_LDADD = \
|
||||
libtestgencpp.la \
|
||||
$(BOOST_TEST_LDADD)
|
||||
|
||||
#
|
||||
# SpecializationTest
|
||||
#
|
||||
SpecializationTest_SOURCES = \
|
||||
SpecializationTest.cpp
|
||||
|
||||
SpecializationTest_LDADD = \
|
||||
libtestgencpp.la \
|
||||
$(BOOST_TEST_LDADD)
|
||||
|
||||
concurrency_test_SOURCES = \
|
||||
concurrency/Tests.cpp \
|
||||
concurrency/ThreadFactoryTests.h \
|
||||
concurrency/ThreadManagerTests.h \
|
||||
concurrency/TimerManagerTests.h
|
||||
|
||||
concurrency_test_LDADD = \
|
||||
$(top_builddir)/lib/cpp/libthrift.la
|
||||
|
||||
link_test_SOURCES = \
|
||||
link/LinkTest.cpp \
|
||||
link/TemplatedService1.cpp \
|
||||
link/TemplatedService2.cpp
|
||||
|
||||
processor_test_SOURCES = \
|
||||
processor/ProcessorTest.cpp \
|
||||
processor/EventLog.cpp \
|
||||
processor/ServerThread.cpp \
|
||||
processor/EventLog.h \
|
||||
processor/Handlers.h \
|
||||
processor/ServerThread.h
|
||||
|
||||
processor_test_LDADD = libprocessortest.la \
|
||||
$(top_builddir)/lib/cpp/libthrift.la \
|
||||
$(top_builddir)/lib/cpp/libthriftnb.la \
|
||||
$(BOOST_TEST_LDADD) \
|
||||
$(BOOST_LDFLAGS) \
|
||||
$(LIBEVENT_LIBS)
|
||||
|
||||
OpenSSLManualInitTest_SOURCES = \
|
||||
OpenSSLManualInitTest.cpp
|
||||
|
||||
OpenSSLManualInitTest_LDADD = \
|
||||
$(top_builddir)/lib/cpp/libthrift.la \
|
||||
$(BOOST_TEST_LDADD) \
|
||||
$(OPENSSL_LDFLAGS) \
|
||||
$(OPENSSL_LIBS)
|
||||
|
||||
#
|
||||
# Common thrift code generation rules
|
||||
#
|
||||
THRIFT = $(top_builddir)/compiler/cpp/thrift
|
||||
|
||||
gen-cpp/DebugProtoTest_types.cpp gen-cpp/DebugProtoTest_types.h gen-cpp/EmptyService.cpp gen-cpp/EmptyService.h: $(top_srcdir)/test/DebugProtoTest.thrift
|
||||
$(THRIFT) --gen cpp $<
|
||||
|
||||
gen-cpp/EnumTest_types.cpp gen-cpp/EnumTest_types.h: $(top_srcdir)/test/EnumTest.thrift
|
||||
$(THRIFT) --gen cpp $<
|
||||
|
||||
gen-cpp/TypedefTest_types.cpp gen-cpp/TypedefTest_types.h: $(top_srcdir)/test/TypedefTest.thrift
|
||||
$(THRIFT) --gen cpp $<
|
||||
|
||||
gen-cpp/OptionalRequiredTest_types.cpp gen-cpp/OptionalRequiredTest_types.h: $(top_srcdir)/test/OptionalRequiredTest.thrift
|
||||
$(THRIFT) --gen cpp $<
|
||||
|
||||
gen-cpp/Recursive_types.cpp gen-cpp/Recursive_types.h: $(top_srcdir)/test/Recursive.thrift
|
||||
$(THRIFT) --gen cpp $<
|
||||
|
||||
gen-cpp/Service.cpp gen-cpp/StressTest_types.cpp: $(top_srcdir)/test/StressTest.thrift
|
||||
$(THRIFT) --gen cpp $<
|
||||
|
||||
gen-cpp/SecondService.cpp gen-cpp/ThriftTest_constants.cpp gen-cpp/ThriftTest.cpp gen-cpp/ThriftTest_types.cpp gen-cpp/ThriftTest_types.h: $(top_srcdir)/test/ThriftTest.thrift
|
||||
$(THRIFT) --gen cpp $<
|
||||
|
||||
gen-cpp/ChildService.cpp gen-cpp/ChildService.h gen-cpp/ParentService.cpp gen-cpp/ParentService.h gen-cpp/proc_types.cpp gen-cpp/proc_types.h: processor/proc.thrift
|
||||
$(THRIFT) --gen cpp:templates,cob_style $<
|
||||
|
||||
AM_CPPFLAGS = $(BOOST_CPPFLAGS) -I$(top_srcdir)/lib/cpp/src -D__STDC_LIMIT_MACROS -I.
|
||||
AM_LDFLAGS = $(BOOST_LDFLAGS)
|
||||
AM_CXXFLAGS = -Wall -Wextra -pedantic
|
||||
|
||||
clean-local:
|
||||
$(RM) gen-cpp/*
|
||||
|
||||
EXTRA_DIST = \
|
||||
concurrency \
|
||||
processor \
|
||||
qt \
|
||||
CMakeLists.txt \
|
||||
DebugProtoTest_extras.cpp \
|
||||
ThriftTest_extras.cpp
|
94
vendor/git.apache.org/thrift.git/lib/cpp/test/OpenSSLManualInitTest.cpp
generated
vendored
Normal file
94
vendor/git.apache.org/thrift.git/lib/cpp/test/OpenSSLManualInitTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
// To show that this test actually tests something, you can change
|
||||
// MANUAL_OPENSSL_INIT to 0 to cause automatic OpenSSL init/cleanup,
|
||||
// which will cause the test to fail
|
||||
#define MANUAL_OPENSSL_INIT 1
|
||||
#ifdef _WIN32
|
||||
#include <WinSock2.h>
|
||||
#endif
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <openssl/evp.h>
|
||||
#include <thrift/transport/TSSLSocket.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace apache::thrift::transport;
|
||||
|
||||
void make_isolated_sslsocketfactory() {
|
||||
// Here we create an isolated TSSLSocketFactory to ensure the
|
||||
// constructor and destructor of TSSLSocketFactory get run. Thus
|
||||
// without manual initialization normally OpenSSL would be
|
||||
// uninitialized after this function.
|
||||
TSSLSocketFactory factory;
|
||||
}
|
||||
|
||||
void openssl_init() {
|
||||
#if MANUAL_OPENSSL_INIT
|
||||
TSSLSocketFactory::setManualOpenSSLInitialization(true);
|
||||
initializeOpenSSL();
|
||||
#endif
|
||||
}
|
||||
|
||||
void openssl_cleanup() {
|
||||
#if MANUAL_OPENSSL_INIT
|
||||
cleanupOpenSSL();
|
||||
#endif
|
||||
}
|
||||
|
||||
void test_openssl_availability() {
|
||||
// Check whether Thrift leaves OpenSSL functionality available after
|
||||
// the last TSSLSocketFactory is destroyed when manual
|
||||
// initialization is set
|
||||
openssl_init();
|
||||
make_isolated_sslsocketfactory();
|
||||
|
||||
// The following function is one that will fail if OpenSSL is
|
||||
// uninitialized. It might also fail on very old versions of
|
||||
// OpenSSL...
|
||||
const EVP_MD* md = EVP_get_digestbyname("SHA256");
|
||||
BOOST_CHECK(md != NULL);
|
||||
openssl_cleanup();
|
||||
}
|
||||
|
||||
#ifdef BOOST_TEST_DYN_LINK
|
||||
bool init_unit_test_suite() {
|
||||
boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite();
|
||||
suite->p_name.value = "OpenSSLManualInit";
|
||||
|
||||
suite->add(BOOST_TEST_CASE(test_openssl_availability));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main( int argc, char* argv[] ) {
|
||||
return ::boost::unit_test::unit_test_main(&init_unit_test_suite,argc,argv);
|
||||
}
|
||||
#else
|
||||
boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) {
|
||||
THRIFT_UNUSED_VARIABLE(argc);
|
||||
THRIFT_UNUSED_VARIABLE(argv);
|
||||
boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite();
|
||||
suite->p_name.value = "OpenSSLManualInit";
|
||||
|
||||
suite->add(BOOST_TEST_CASE(test_openssl_availability));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
386
vendor/git.apache.org/thrift.git/lib/cpp/test/OptionalRequiredTest.cpp
generated
vendored
Normal file
386
vendor/git.apache.org/thrift.git/lib/cpp/test/OptionalRequiredTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,386 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contains some contributions under the Thrift Software License.
|
||||
* Please see doc/old-thrift-license.txt in the Thrift distribution for
|
||||
* details.
|
||||
*/
|
||||
|
||||
#include <map>
|
||||
#include <thrift/protocol/TDebugProtocol.h>
|
||||
#include <thrift/protocol/TBinaryProtocol.h>
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
#include "gen-cpp/OptionalRequiredTest_types.h"
|
||||
|
||||
#define BOOST_TEST_MODULE OptionalRequiredTest
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using namespace thrift::test;
|
||||
using namespace apache::thrift;
|
||||
using namespace apache::thrift::transport;
|
||||
using namespace apache::thrift::protocol;
|
||||
|
||||
/*
|
||||
template<typename Struct>
|
||||
void trywrite(const Struct& s, bool should_work) {
|
||||
bool worked;
|
||||
try {
|
||||
TBinaryProtocol protocol(boost::shared_ptr<TTransport>(new TMemoryBuffer));
|
||||
s.write(&protocol);
|
||||
worked = true;
|
||||
} catch (TProtocolException & ex) {
|
||||
worked = false;
|
||||
}
|
||||
BOOST_CHECK(worked == should_work);
|
||||
}
|
||||
*/
|
||||
|
||||
template <typename Struct1, typename Struct2>
|
||||
void write_to_read(const Struct1& w, Struct2& r) {
|
||||
TBinaryProtocol protocol(boost::shared_ptr<TTransport>(new TMemoryBuffer));
|
||||
w.write(&protocol);
|
||||
r.read(&protocol);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_1) {
|
||||
OldSchool o;
|
||||
|
||||
const std::string expected_result(
|
||||
"OldSchool {\n"
|
||||
" 01: im_int (i16) = 0,\n"
|
||||
" 02: im_str (string) = \"\",\n"
|
||||
" 03: im_big (list) = list<map>[0] {\n"
|
||||
" },\n"
|
||||
"}");
|
||||
const std::string result(apache::thrift::ThriftDebugString(o));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_2_1) {
|
||||
Simple s;
|
||||
|
||||
const std::string expected_result(
|
||||
"Simple {\n"
|
||||
" 01: im_default (i16) = 0,\n"
|
||||
" 02: im_required (i16) = 0,\n"
|
||||
"}");
|
||||
const std::string result(apache::thrift::ThriftDebugString(s));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_2_2) {
|
||||
Simple s;
|
||||
s.im_optional = 10;
|
||||
|
||||
const std::string expected_result(
|
||||
"Simple {\n"
|
||||
" 01: im_default (i16) = 0,\n"
|
||||
" 02: im_required (i16) = 0,\n"
|
||||
"}");
|
||||
const std::string result(apache::thrift::ThriftDebugString(s));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_2_3) {
|
||||
Simple s;
|
||||
s.im_optional = 10;
|
||||
s.__isset.im_optional = true;
|
||||
|
||||
const std::string expected_result(
|
||||
"Simple {\n"
|
||||
" 01: im_default (i16) = 0,\n"
|
||||
" 02: im_required (i16) = 0,\n"
|
||||
" 03: im_optional (i16) = 10,\n"
|
||||
"}");
|
||||
const std::string result(apache::thrift::ThriftDebugString(s));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_2_4) {
|
||||
Simple s;
|
||||
s.__isset.im_optional = true;
|
||||
|
||||
const std::string expected_result(
|
||||
"Simple {\n"
|
||||
" 01: im_default (i16) = 0,\n"
|
||||
" 02: im_required (i16) = 0,\n"
|
||||
" 03: im_optional (i16) = 0,\n"
|
||||
"}");
|
||||
const std::string result(apache::thrift::ThriftDebugString(s));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_2_5) {
|
||||
Simple s;
|
||||
s.__isset.im_optional = true;
|
||||
s.im_optional = 10;
|
||||
|
||||
const std::string expected_result(
|
||||
"Simple {\n"
|
||||
" 01: im_default (i16) = 0,\n"
|
||||
" 02: im_required (i16) = 0,\n"
|
||||
" 03: im_optional (i16) = 10,\n"
|
||||
"}");
|
||||
const std::string result(apache::thrift::ThriftDebugString(s));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_3) {
|
||||
// assign/copy-construct with non-required fields
|
||||
|
||||
Simple s1, s2;
|
||||
s1.__isset.im_default = true;
|
||||
s1.__set_im_optional(10);
|
||||
BOOST_CHECK(s1.__isset.im_default);
|
||||
BOOST_CHECK(s1.__isset.im_optional);
|
||||
|
||||
s2 = s1;
|
||||
|
||||
BOOST_CHECK(s2.__isset.im_default);
|
||||
BOOST_CHECK(s2.__isset.im_optional);
|
||||
|
||||
Simple s3(s1);
|
||||
|
||||
BOOST_CHECK(s3.__isset.im_default);
|
||||
BOOST_CHECK(s3.__isset.im_optional);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_4) {
|
||||
// Write-to-read with optional fields.
|
||||
|
||||
Simple s1, s2, s3;
|
||||
s1.im_optional = 10;
|
||||
BOOST_CHECK(!s1.__isset.im_default);
|
||||
// BOOST_CHECK(!s1.__isset.im_required); // Compile error.
|
||||
BOOST_CHECK(!s1.__isset.im_optional);
|
||||
|
||||
write_to_read(s1, s2);
|
||||
|
||||
BOOST_CHECK(s2.__isset.im_default);
|
||||
// BOOST_CHECK( s2.__isset.im_required); // Compile error.
|
||||
BOOST_CHECK(!s2.__isset.im_optional);
|
||||
BOOST_CHECK(s3.im_optional == 0);
|
||||
|
||||
s1.__isset.im_optional = true;
|
||||
write_to_read(s1, s3);
|
||||
|
||||
BOOST_CHECK(s3.__isset.im_default);
|
||||
// BOOST_CHECK( s3.__isset.im_required); // Compile error.
|
||||
BOOST_CHECK(s3.__isset.im_optional);
|
||||
BOOST_CHECK(s3.im_optional == 10);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_5) {
|
||||
// Writing between optional and default.
|
||||
|
||||
Tricky1 t1;
|
||||
Tricky2 t2;
|
||||
|
||||
t2.im_optional = 10;
|
||||
write_to_read(t2, t1);
|
||||
write_to_read(t1, t2);
|
||||
BOOST_CHECK(!t1.__isset.im_default);
|
||||
BOOST_CHECK(t2.__isset.im_optional);
|
||||
BOOST_CHECK(t1.im_default == t2.im_optional);
|
||||
BOOST_CHECK(t1.im_default == 0);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_6) {
|
||||
// Writing between default and required.
|
||||
|
||||
Tricky1 t1;
|
||||
Tricky3 t3;
|
||||
write_to_read(t1, t3);
|
||||
write_to_read(t3, t1);
|
||||
BOOST_CHECK(t1.__isset.im_default);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_7) {
|
||||
// Writing between optional and required.
|
||||
|
||||
Tricky2 t2;
|
||||
Tricky3 t3;
|
||||
t2.__isset.im_optional = true;
|
||||
write_to_read(t2, t3);
|
||||
write_to_read(t3, t2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_8) {
|
||||
// Mu-hu-ha-ha-ha!
|
||||
|
||||
Tricky2 t2;
|
||||
Tricky3 t3;
|
||||
try {
|
||||
write_to_read(t2, t3);
|
||||
abort();
|
||||
} catch (const TProtocolException&) {
|
||||
}
|
||||
|
||||
write_to_read(t3, t2);
|
||||
BOOST_CHECK(t2.__isset.im_optional);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_9) {
|
||||
Complex c;
|
||||
|
||||
const std::string expected_result(
|
||||
"Complex {\n"
|
||||
" 01: cp_default (i16) = 0,\n"
|
||||
" 02: cp_required (i16) = 0,\n"
|
||||
" 04: the_map (map) = map<i16,struct>[0] {\n"
|
||||
" },\n"
|
||||
" 05: req_simp (struct) = Simple {\n"
|
||||
" 01: im_default (i16) = 0,\n"
|
||||
" 02: im_required (i16) = 0,\n"
|
||||
" },\n"
|
||||
"}");
|
||||
const std::string result(apache::thrift::ThriftDebugString(c));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_10) {
|
||||
Tricky1 t1;
|
||||
Tricky2 t2;
|
||||
// Compile error.
|
||||
//(void)(t1 == t2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_11) {
|
||||
OldSchool o1, o2, o3;
|
||||
BOOST_CHECK(o1 == o2);
|
||||
o1.im_int = o2.im_int = 10;
|
||||
BOOST_CHECK(o1 == o2);
|
||||
o1.__isset.im_int = true;
|
||||
o2.__isset.im_int = false;
|
||||
BOOST_CHECK(o1 == o2);
|
||||
o1.im_int = 20;
|
||||
o1.__isset.im_int = false;
|
||||
BOOST_CHECK(o1 != o2);
|
||||
o1.im_int = 10;
|
||||
BOOST_CHECK(o1 == o2);
|
||||
o1.im_str = o2.im_str = "foo";
|
||||
BOOST_CHECK(o1 == o2);
|
||||
o1.__isset.im_str = o2.__isset.im_str = true;
|
||||
BOOST_CHECK(o1 == o2);
|
||||
std::map<int32_t, std::string> mymap;
|
||||
mymap[1] = "bar";
|
||||
mymap[2] = "baz";
|
||||
o1.im_big.push_back(std::map<int32_t, std::string>());
|
||||
BOOST_CHECK(o1 != o2);
|
||||
o2.im_big.push_back(std::map<int32_t, std::string>());
|
||||
BOOST_CHECK(o1 == o2);
|
||||
o2.im_big.push_back(mymap);
|
||||
BOOST_CHECK(o1 != o2);
|
||||
o1.im_big.push_back(mymap);
|
||||
BOOST_CHECK(o1 == o2);
|
||||
|
||||
TBinaryProtocol protocol(boost::shared_ptr<TTransport>(new TMemoryBuffer));
|
||||
o1.write(&protocol);
|
||||
|
||||
o1.im_big.push_back(mymap);
|
||||
mymap[3] = "qux";
|
||||
o2.im_big.push_back(mymap);
|
||||
BOOST_CHECK(o1 != o2);
|
||||
o1.im_big.back()[3] = "qux";
|
||||
BOOST_CHECK(o1 == o2);
|
||||
|
||||
o3.read(&protocol);
|
||||
o3.im_big.push_back(mymap);
|
||||
BOOST_CHECK(o1 == o3);
|
||||
|
||||
const std::string expected_result(
|
||||
"OldSchool {\n"
|
||||
" 01: im_int (i16) = 10,\n"
|
||||
" 02: im_str (string) = \"foo\",\n"
|
||||
" 03: im_big (list) = list<map>[3] {\n"
|
||||
" [0] = map<i32,string>[0] {\n"
|
||||
" },\n"
|
||||
" [1] = map<i32,string>[2] {\n"
|
||||
" 1 -> \"bar\",\n"
|
||||
" 2 -> \"baz\",\n"
|
||||
" },\n"
|
||||
" [2] = map<i32,string>[3] {\n"
|
||||
" 1 -> \"bar\",\n"
|
||||
" 2 -> \"baz\",\n"
|
||||
" 3 -> \"qux\",\n"
|
||||
" },\n"
|
||||
" },\n"
|
||||
"}");
|
||||
const std::string result(apache::thrift::ThriftDebugString(o3));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_12) {
|
||||
Tricky2 t1, t2;
|
||||
BOOST_CHECK(t1.__isset.im_optional == false);
|
||||
BOOST_CHECK(t2.__isset.im_optional == false);
|
||||
BOOST_CHECK(t1 == t2);
|
||||
t1.im_optional = 5;
|
||||
BOOST_CHECK(t1 == t2);
|
||||
t2.im_optional = 5;
|
||||
BOOST_CHECK(t1 == t2);
|
||||
t1.__isset.im_optional = true;
|
||||
BOOST_CHECK(t1 != t2);
|
||||
t2.__isset.im_optional = true;
|
||||
BOOST_CHECK(t1 == t2);
|
||||
t1.im_optional = 10;
|
||||
BOOST_CHECK(t1 != t2);
|
||||
t2.__isset.im_optional = false;
|
||||
BOOST_CHECK(t1 != t2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_optional_required_13) {
|
||||
OptionalDefault t1, t2;
|
||||
|
||||
BOOST_CHECK(t1.__isset.opt_int == true);
|
||||
BOOST_CHECK(t1.__isset.opt_str == true);
|
||||
BOOST_CHECK(t1.opt_int == t2.opt_int);
|
||||
BOOST_CHECK(t1.opt_str == t2.opt_str);
|
||||
|
||||
write_to_read(t1, t2);
|
||||
BOOST_CHECK(t2.__isset.opt_int == true);
|
||||
BOOST_CHECK(t2.__isset.opt_str == true);
|
||||
BOOST_CHECK(t1.opt_int == t2.opt_int);
|
||||
BOOST_CHECK(t1.opt_str == t2.opt_str);
|
||||
|
||||
const std::string expected_result(
|
||||
"OptionalDefault {\n"
|
||||
" 01: opt_int (i16) = 1234,\n"
|
||||
" 02: opt_str (string) = \"default\",\n"
|
||||
"}");
|
||||
const std::string result(apache::thrift::ThriftDebugString(t2));
|
||||
|
||||
BOOST_CHECK_MESSAGE(!expected_result.compare(result),
|
||||
"Expected:\n" << expected_result << "\nGotten:\n" << result);
|
||||
}
|
159
vendor/git.apache.org/thrift.git/lib/cpp/test/RWMutexStarveTest.cpp
generated
vendored
Normal file
159
vendor/git.apache.org/thrift.git/lib/cpp/test/RWMutexStarveTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <iostream>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include "thrift/concurrency/Mutex.h"
|
||||
#include "thrift/concurrency/PosixThreadFactory.h"
|
||||
|
||||
using boost::shared_ptr;
|
||||
using boost::unit_test::test_suite;
|
||||
using boost::unit_test::framework::master_test_suite;
|
||||
|
||||
using namespace apache::thrift::concurrency;
|
||||
using namespace std;
|
||||
|
||||
class Locker : public Runnable {
|
||||
protected:
|
||||
Locker(boost::shared_ptr<ReadWriteMutex> rwlock, bool writer)
|
||||
: rwlock_(rwlock), writer_(writer), started_(false), gotLock_(false), signaled_(false) {}
|
||||
|
||||
public:
|
||||
virtual void run() {
|
||||
started_ = true;
|
||||
if (writer_) {
|
||||
rwlock_->acquireWrite();
|
||||
} else {
|
||||
rwlock_->acquireRead();
|
||||
}
|
||||
gotLock_ = true;
|
||||
while (!signaled_) {
|
||||
usleep(5000);
|
||||
}
|
||||
rwlock_->release();
|
||||
}
|
||||
|
||||
bool started() const { return started_; }
|
||||
bool gotLock() const { return gotLock_; }
|
||||
void signal() { signaled_ = true; }
|
||||
|
||||
protected:
|
||||
boost::shared_ptr<ReadWriteMutex> rwlock_;
|
||||
bool writer_;
|
||||
volatile bool started_;
|
||||
volatile bool gotLock_;
|
||||
volatile bool signaled_;
|
||||
};
|
||||
|
||||
class Reader : public Locker {
|
||||
public:
|
||||
Reader(boost::shared_ptr<ReadWriteMutex> rwlock) : Locker(rwlock, false) {}
|
||||
};
|
||||
|
||||
class Writer : public Locker {
|
||||
public:
|
||||
Writer(boost::shared_ptr<ReadWriteMutex> rwlock) : Locker(rwlock, true) {}
|
||||
};
|
||||
|
||||
void test_starve(PosixThreadFactory::POLICY policy) {
|
||||
// the man pages for pthread_wrlock_rdlock suggest that any OS guarantee about
|
||||
// writer starvation may be influenced by the scheduling policy, so let's try
|
||||
// all 3 policies to see if any of them work.
|
||||
PosixThreadFactory factory(policy);
|
||||
factory.setDetached(false);
|
||||
|
||||
boost::shared_ptr<ReadWriteMutex> rwlock(new NoStarveReadWriteMutex());
|
||||
|
||||
boost::shared_ptr<Reader> reader1(new Reader(rwlock));
|
||||
boost::shared_ptr<Reader> reader2(new Reader(rwlock));
|
||||
boost::shared_ptr<Writer> writer(new Writer(rwlock));
|
||||
|
||||
boost::shared_ptr<Thread> treader1 = factory.newThread(reader1);
|
||||
boost::shared_ptr<Thread> treader2 = factory.newThread(reader2);
|
||||
boost::shared_ptr<Thread> twriter = factory.newThread(writer);
|
||||
|
||||
// launch a reader and make sure he has the lock
|
||||
treader1->start();
|
||||
while (!reader1->gotLock()) {
|
||||
usleep(2000);
|
||||
}
|
||||
|
||||
// launch a writer and make sure he's blocked on the lock
|
||||
twriter->start();
|
||||
while (!writer->started()) {
|
||||
usleep(2000);
|
||||
}
|
||||
// tricky part... we can never be 100% sure that the writer is actually
|
||||
// blocked on the lock, but we can pretty reasonably sure because we know
|
||||
// he just executed the line immediately before getting the lock, and
|
||||
// we'll wait a full second for him to get on it.
|
||||
sleep(1);
|
||||
|
||||
// launch a second reader... if the RWMutex guarantees that writers won't
|
||||
// starve, this reader should not be able to acquire the lock until the writer
|
||||
// has acquired and released it.
|
||||
treader2->start();
|
||||
while (!reader2->started()) {
|
||||
usleep(2000);
|
||||
}
|
||||
// again... can't be 100% sure the reader is waiting on (or has) the lock
|
||||
// but we can be close.
|
||||
sleep(1);
|
||||
|
||||
// tell reader 1 to let go of the lock
|
||||
reader1->signal();
|
||||
|
||||
// wait for someone to get the lock
|
||||
while (!reader2->gotLock() && !writer->gotLock()) {
|
||||
usleep(2000);
|
||||
}
|
||||
|
||||
// the test succeeded if the WRITER got the lock.
|
||||
bool success = writer->gotLock();
|
||||
|
||||
// tell everyone we're done and wait for them to finish
|
||||
reader2->signal();
|
||||
writer->signal();
|
||||
treader1->join();
|
||||
treader2->join();
|
||||
twriter->join();
|
||||
|
||||
// make sure it worked.
|
||||
BOOST_CHECK_MESSAGE(success, "writer is starving");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(RWMutexStarveTest)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_starve_other) {
|
||||
test_starve(PosixThreadFactory::OTHER);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_starve_rr) {
|
||||
test_starve(PosixThreadFactory::ROUND_ROBIN);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_starve_fifo) {
|
||||
test_starve(PosixThreadFactory::FIFO);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
91
vendor/git.apache.org/thrift.git/lib/cpp/test/RecursiveTest.cpp
generated
vendored
Normal file
91
vendor/git.apache.org/thrift.git/lib/cpp/test/RecursiveTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Contains some contributions under the Thrift Software License.
|
||||
* Please see doc/old-thrift-license.txt in the Thrift distribution for
|
||||
* details.
|
||||
*/
|
||||
|
||||
#include "gen-cpp/Recursive_types.h"
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
#include <thrift/protocol/TBinaryProtocol.h>
|
||||
|
||||
#define BOOST_TEST_MODULE RecursiveTest
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using apache::thrift::transport::TMemoryBuffer;
|
||||
using apache::thrift::protocol::TBinaryProtocol;
|
||||
using boost::shared_ptr;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_recursive_1) {
|
||||
shared_ptr<TMemoryBuffer> buf(new TMemoryBuffer());
|
||||
shared_ptr<TBinaryProtocol> prot(new TBinaryProtocol(buf));
|
||||
|
||||
RecTree tree;
|
||||
RecTree child;
|
||||
tree.children.push_back(child);
|
||||
|
||||
tree.write(prot.get());
|
||||
|
||||
RecTree result;
|
||||
result.read(prot.get());
|
||||
BOOST_CHECK(tree == result);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_recursive_2) {
|
||||
shared_ptr<TMemoryBuffer> buf(new TMemoryBuffer());
|
||||
shared_ptr<TBinaryProtocol> prot(new TBinaryProtocol(buf));
|
||||
|
||||
RecList l;
|
||||
boost::shared_ptr<RecList> l2(new RecList);
|
||||
l.nextitem = l2;
|
||||
|
||||
l.write(prot.get());
|
||||
|
||||
RecList resultlist;
|
||||
resultlist.read(prot.get());
|
||||
BOOST_CHECK(resultlist.nextitem != NULL);
|
||||
BOOST_CHECK(resultlist.nextitem->nextitem == NULL);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_recursive_3) {
|
||||
shared_ptr<TMemoryBuffer> buf(new TMemoryBuffer());
|
||||
shared_ptr<TBinaryProtocol> prot(new TBinaryProtocol(buf));
|
||||
|
||||
CoRec c;
|
||||
boost::shared_ptr<CoRec2> r(new CoRec2);
|
||||
c.other = r;
|
||||
|
||||
c.write(prot.get());
|
||||
|
||||
c.read(prot.get());
|
||||
BOOST_CHECK(c.other != NULL);
|
||||
BOOST_CHECK(c.other->other.other == NULL);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_recursive_4) {
|
||||
shared_ptr<TMemoryBuffer> buf(new TMemoryBuffer());
|
||||
shared_ptr<TBinaryProtocol> prot(new TBinaryProtocol(buf));
|
||||
|
||||
boost::shared_ptr<RecList> depthLimit(new RecList);
|
||||
depthLimit->nextitem = depthLimit;
|
||||
BOOST_CHECK_THROW(depthLimit->write(prot.get()),
|
||||
apache::thrift::protocol::TProtocolException);
|
||||
|
||||
depthLimit->nextitem.reset();
|
||||
}
|
276
vendor/git.apache.org/thrift.git/lib/cpp/test/SecurityTest.cpp
generated
vendored
Normal file
276
vendor/git.apache.org/thrift.git/lib/cpp/test/SecurityTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE SecurityTest
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <thrift/transport/TSSLServerSocket.h>
|
||||
#include <thrift/transport/TSSLSocket.h>
|
||||
#include <thrift/transport/TTransport.h>
|
||||
#include <vector>
|
||||
#ifdef __linux__
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
using apache::thrift::transport::TSSLServerSocket;
|
||||
using apache::thrift::transport::TServerTransport;
|
||||
using apache::thrift::transport::TSSLSocket;
|
||||
using apache::thrift::transport::TSSLSocketFactory;
|
||||
using apache::thrift::transport::TTransport;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
using apache::thrift::transport::TTransportFactory;
|
||||
|
||||
boost::filesystem::path keyDir;
|
||||
boost::filesystem::path certFile(const std::string& filename)
|
||||
{
|
||||
return keyDir / filename;
|
||||
}
|
||||
boost::mutex gMutex;
|
||||
|
||||
struct GlobalFixture
|
||||
{
|
||||
GlobalFixture()
|
||||
{
|
||||
using namespace boost::unit_test::framework;
|
||||
for (int i = 0; i < master_test_suite().argc; ++i)
|
||||
{
|
||||
BOOST_TEST_MESSAGE(boost::format("argv[%1%] = \"%2%\"") % i % master_test_suite().argv[i]);
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
// OpenSSL calls send() without MSG_NOSIGPIPE so writing to a socket that has
|
||||
// disconnected can cause a SIGPIPE signal...
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
TSSLSocketFactory::setManualOpenSSLInitialization(true);
|
||||
apache::thrift::transport::initializeOpenSSL();
|
||||
|
||||
keyDir = boost::filesystem::current_path().parent_path().parent_path().parent_path() / "test" / "keys";
|
||||
if (!boost::filesystem::exists(certFile("server.crt")))
|
||||
{
|
||||
keyDir = boost::filesystem::path(master_test_suite().argv[master_test_suite().argc - 1]);
|
||||
if (!boost::filesystem::exists(certFile("server.crt")))
|
||||
{
|
||||
throw std::invalid_argument("The last argument to this test must be the directory containing the test certificate(s).");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~GlobalFixture()
|
||||
{
|
||||
apache::thrift::transport::cleanupOpenSSL();
|
||||
#ifdef __linux__
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#if (BOOST_VERSION >= 105900)
|
||||
BOOST_GLOBAL_FIXTURE(GlobalFixture);
|
||||
#else
|
||||
BOOST_GLOBAL_FIXTURE(GlobalFixture)
|
||||
#endif
|
||||
|
||||
struct SecurityFixture
|
||||
{
|
||||
void server(apache::thrift::transport::SSLProtocol protocol)
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::mutex::scoped_lock lock(mMutex);
|
||||
|
||||
boost::shared_ptr<TSSLSocketFactory> pServerSocketFactory;
|
||||
boost::shared_ptr<TSSLServerSocket> pServerSocket;
|
||||
|
||||
pServerSocketFactory.reset(new TSSLSocketFactory(static_cast<apache::thrift::transport::SSLProtocol>(protocol)));
|
||||
pServerSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
|
||||
pServerSocketFactory->loadCertificate(certFile("server.crt").string().c_str());
|
||||
pServerSocketFactory->loadPrivateKey(certFile("server.key").string().c_str());
|
||||
pServerSocketFactory->server(true);
|
||||
pServerSocket.reset(new TSSLServerSocket("localhost", 0, pServerSocketFactory));
|
||||
boost::shared_ptr<TTransport> connectedClient;
|
||||
|
||||
try
|
||||
{
|
||||
pServerSocket->listen();
|
||||
mPort = pServerSocket->getPort();
|
||||
mCVar.notify_one();
|
||||
lock.unlock();
|
||||
|
||||
connectedClient = pServerSocket->accept();
|
||||
uint8_t buf[2];
|
||||
buf[0] = 'O';
|
||||
buf[1] = 'K';
|
||||
connectedClient->write(&buf[0], 2);
|
||||
connectedClient->flush();
|
||||
}
|
||||
|
||||
catch (apache::thrift::transport::TTransportException& ex)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(gMutex);
|
||||
BOOST_TEST_MESSAGE(boost::format("SRV %1% Exception: %2%") % boost::this_thread::get_id() % ex.what());
|
||||
}
|
||||
|
||||
if (connectedClient)
|
||||
{
|
||||
connectedClient->close();
|
||||
connectedClient.reset();
|
||||
}
|
||||
|
||||
pServerSocket->close();
|
||||
pServerSocket.reset();
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_FAIL(boost::format("%1%: %2%") % typeid(ex).name() % ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
void client(apache::thrift::transport::SSLProtocol protocol)
|
||||
{
|
||||
try
|
||||
{
|
||||
boost::shared_ptr<TSSLSocketFactory> pClientSocketFactory;
|
||||
boost::shared_ptr<TSSLSocket> pClientSocket;
|
||||
|
||||
try
|
||||
{
|
||||
pClientSocketFactory.reset(new TSSLSocketFactory(static_cast<apache::thrift::transport::SSLProtocol>(protocol)));
|
||||
pClientSocketFactory->authenticate(true);
|
||||
pClientSocketFactory->loadCertificate(certFile("client.crt").string().c_str());
|
||||
pClientSocketFactory->loadPrivateKey(certFile("client.key").string().c_str());
|
||||
pClientSocketFactory->loadTrustedCertificates(certFile("CA.pem").string().c_str());
|
||||
pClientSocket = pClientSocketFactory->createSocket("localhost", mPort);
|
||||
pClientSocket->open();
|
||||
|
||||
uint8_t buf[3];
|
||||
buf[0] = 0;
|
||||
buf[1] = 0;
|
||||
BOOST_CHECK_EQUAL(2, pClientSocket->read(&buf[0], 2));
|
||||
BOOST_CHECK_EQUAL(0, memcmp(&buf[0], "OK", 2));
|
||||
mConnected = true;
|
||||
}
|
||||
catch (apache::thrift::transport::TTransportException& ex)
|
||||
{
|
||||
boost::mutex::scoped_lock lock(gMutex);
|
||||
BOOST_TEST_MESSAGE(boost::format("CLI %1% Exception: %2%") % boost::this_thread::get_id() % ex.what());
|
||||
}
|
||||
|
||||
if (pClientSocket)
|
||||
{
|
||||
pClientSocket->close();
|
||||
pClientSocket.reset();
|
||||
}
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_FAIL(boost::format("%1%: %2%") % typeid(ex).name() % ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
static const char *protocol2str(size_t protocol)
|
||||
{
|
||||
static const char *strings[apache::thrift::transport::LATEST + 1] =
|
||||
{
|
||||
"SSLTLS",
|
||||
"SSLv2",
|
||||
"SSLv3",
|
||||
"TLSv1_0",
|
||||
"TLSv1_1",
|
||||
"TLSv1_2"
|
||||
};
|
||||
return strings[protocol];
|
||||
}
|
||||
|
||||
boost::mutex mMutex;
|
||||
boost::condition_variable mCVar;
|
||||
int mPort;
|
||||
bool mConnected;
|
||||
};
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(BOOST_TEST_MODULE, SecurityFixture)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ssl_security_matrix)
|
||||
{
|
||||
try
|
||||
{
|
||||
// matrix of connection success between client and server with different SSLProtocol selections
|
||||
bool matrix[apache::thrift::transport::LATEST + 1][apache::thrift::transport::LATEST + 1] =
|
||||
{
|
||||
// server = SSLTLS SSLv2 SSLv3 TLSv1_0 TLSv1_1 TLSv1_2
|
||||
// client
|
||||
/* SSLTLS */ { true, false, false, true, true, true },
|
||||
/* SSLv2 */ { false, false, false, false, false, false },
|
||||
/* SSLv3 */ { false, false, true, false, false, false },
|
||||
/* TLSv1_0 */ { true, false, false, true, false, false },
|
||||
/* TLSv1_1 */ { true, false, false, false, true, false },
|
||||
/* TLSv1_2 */ { true, false, false, false, false, true }
|
||||
};
|
||||
|
||||
for (size_t si = 0; si <= apache::thrift::transport::LATEST; ++si)
|
||||
{
|
||||
for (size_t ci = 0; ci <= apache::thrift::transport::LATEST; ++ci)
|
||||
{
|
||||
if (si == 1 || ci == 1)
|
||||
{
|
||||
// Skip all SSLv2 cases - protocol not supported
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef OPENSSL_NO_SSL3
|
||||
if (si == 2 || ci == 2)
|
||||
{
|
||||
// Skip all SSLv3 cases - protocol not supported
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
|
||||
boost::mutex::scoped_lock lock(mMutex);
|
||||
|
||||
BOOST_TEST_MESSAGE(boost::format("TEST: Server = %1%, Client = %2%")
|
||||
% protocol2str(si) % protocol2str(ci));
|
||||
|
||||
mConnected = false;
|
||||
boost::thread_group threads;
|
||||
threads.create_thread(boost::bind(&SecurityFixture::server, this, static_cast<apache::thrift::transport::SSLProtocol>(si)));
|
||||
mCVar.wait(lock); // wait for listen() to succeed
|
||||
lock.unlock();
|
||||
threads.create_thread(boost::bind(&SecurityFixture::client, this, static_cast<apache::thrift::transport::SSLProtocol>(ci)));
|
||||
threads.join_all();
|
||||
|
||||
BOOST_CHECK_MESSAGE(mConnected == matrix[ci][si],
|
||||
boost::format(" Server = %1%, Client = %2% expected mConnected == %3% but was %4%")
|
||||
% protocol2str(si) % protocol2str(ci) % matrix[ci][si] % mConnected);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& ex)
|
||||
{
|
||||
BOOST_FAIL(boost::format("%1%: %2%") % typeid(ex).name() % ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
103
vendor/git.apache.org/thrift.git/lib/cpp/test/SpecializationTest.cpp
generated
vendored
Normal file
103
vendor/git.apache.org/thrift.git/lib/cpp/test/SpecializationTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,103 @@
|
|||
#define _USE_MATH_DEFINES
|
||||
#include <cmath>
|
||||
#include <thrift/transport/TTransportUtils.h>
|
||||
#include <thrift/protocol/TBinaryProtocol.h>
|
||||
#include <gen-cpp/DebugProtoTest_types.h>
|
||||
|
||||
using namespace thrift::test::debug;
|
||||
using namespace apache::thrift::transport;
|
||||
using namespace apache::thrift::protocol;
|
||||
|
||||
#define BOOST_TEST_MODULE SpecializationTest
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
typedef TBinaryProtocolT<TMemoryBuffer> MyProtocol;
|
||||
// typedef TBinaryProtocolT<TTransport> MyProtocol;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_specialization_1) {
|
||||
OneOfEach ooe;
|
||||
ooe.im_true = true;
|
||||
ooe.im_false = false;
|
||||
ooe.a_bite = 0x7f;
|
||||
ooe.integer16 = 27000;
|
||||
ooe.integer32 = 1 << 24;
|
||||
ooe.integer64 = (uint64_t)6000 * 1000 * 1000;
|
||||
ooe.double_precision = M_PI;
|
||||
ooe.some_characters = "JSON THIS! \"\1";
|
||||
ooe.zomg_unicode = "\xd7\n\a\t";
|
||||
ooe.base64 = "\1\2\3\255";
|
||||
|
||||
Nesting n;
|
||||
n.my_ooe = ooe;
|
||||
n.my_ooe.integer16 = 16;
|
||||
n.my_ooe.integer32 = 32;
|
||||
n.my_ooe.integer64 = 64;
|
||||
n.my_ooe.double_precision = (std::sqrt(5.0) + 1) / 2;
|
||||
n.my_ooe.some_characters = ":R (me going \"rrrr\")";
|
||||
n.my_ooe.zomg_unicode = "\xd3\x80\xe2\x85\xae\xce\x9d\x20\xd0\x9d\xce"
|
||||
"\xbf\xe2\x85\xbf\xd0\xbe\xc9\xa1\xd0\xb3\xd0"
|
||||
"\xb0\xcf\x81\xe2\x84\x8e\x20\xce\x91\x74\x74"
|
||||
"\xce\xb1\xe2\x85\xbd\xce\xba\xc7\x83\xe2\x80"
|
||||
"\xbc";
|
||||
n.my_bonk.type = 31337;
|
||||
n.my_bonk.message = "I am a bonk... xor!";
|
||||
|
||||
HolyMoley hm;
|
||||
|
||||
hm.big.push_back(ooe);
|
||||
hm.big.push_back(n.my_ooe);
|
||||
hm.big[0].a_bite = 0x22;
|
||||
hm.big[1].a_bite = 0x33;
|
||||
|
||||
std::vector<std::string> stage1;
|
||||
stage1.push_back("and a one");
|
||||
stage1.push_back("and a two");
|
||||
hm.contain.insert(stage1);
|
||||
stage1.clear();
|
||||
stage1.push_back("then a one, two");
|
||||
stage1.push_back("three!");
|
||||
stage1.push_back("FOUR!!");
|
||||
hm.contain.insert(stage1);
|
||||
stage1.clear();
|
||||
hm.contain.insert(stage1);
|
||||
|
||||
std::vector<Bonk> stage2;
|
||||
hm.bonks["nothing"] = stage2;
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 1;
|
||||
stage2.back().message = "Wait.";
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 2;
|
||||
stage2.back().message = "What?";
|
||||
hm.bonks["something"] = stage2;
|
||||
stage2.clear();
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 3;
|
||||
stage2.back().message = "quoth";
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 4;
|
||||
stage2.back().message = "the raven";
|
||||
stage2.resize(stage2.size() + 1);
|
||||
stage2.back().type = 5;
|
||||
stage2.back().message = "nevermore";
|
||||
hm.bonks["poe"] = stage2;
|
||||
|
||||
boost::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
|
||||
boost::shared_ptr<TProtocol> proto(new MyProtocol(buffer));
|
||||
|
||||
ooe.write(proto.get());
|
||||
OneOfEach ooe2;
|
||||
ooe2.read(proto.get());
|
||||
|
||||
BOOST_CHECK(ooe == ooe2);
|
||||
|
||||
hm.write(proto.get());
|
||||
HolyMoley hm2;
|
||||
hm2.read(proto.get());
|
||||
|
||||
BOOST_CHECK(hm == hm2);
|
||||
|
||||
hm2.big[0].a_bite = 0x00;
|
||||
|
||||
BOOST_CHECK(hm != hm2);
|
||||
}
|
645
vendor/git.apache.org/thrift.git/lib/cpp/test/TBufferBaseTest.cpp
generated
vendored
Normal file
645
vendor/git.apache.org/thrift.git/lib/cpp/test/TBufferBaseTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,645 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <algorithm>
|
||||
#include <boost/test/auto_unit_test.hpp>
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
#include <thrift/transport/TShortReadTransport.h>
|
||||
|
||||
using std::string;
|
||||
using boost::shared_ptr;
|
||||
using apache::thrift::transport::TMemoryBuffer;
|
||||
using apache::thrift::transport::TBufferedTransport;
|
||||
using apache::thrift::transport::TFramedTransport;
|
||||
using apache::thrift::transport::test::TShortReadTransport;
|
||||
|
||||
// Shamelessly copied from ZlibTransport. TODO: refactor.
|
||||
unsigned int dist[][5000] = {
|
||||
{ 1<<15 },
|
||||
|
||||
{
|
||||
5,13,9,1,8,9,11,13,18,48,24,13,21,13,5,11,35,2,4,20,17,72,27,14,15,4,7,26,
|
||||
12,1,14,9,2,16,29,41,7,24,4,27,14,4,1,4,25,3,6,34,10,8,50,2,14,13,55,29,3,
|
||||
43,53,49,14,4,10,32,27,48,1,3,1,11,5,17,16,51,17,30,15,11,9,2,2,11,52,12,2,
|
||||
13,94,1,19,1,38,2,8,43,8,33,7,30,8,17,22,2,15,14,12,34,2,12,6,37,29,74,3,
|
||||
165,16,11,17,5,14,3,10,7,37,11,24,7,1,3,12,37,8,9,34,17,12,8,21,13,37,1,4,
|
||||
30,14,78,4,15,2,40,37,17,12,36,82,14,4,1,4,7,17,11,16,88,77,2,3,15,3,34,11,
|
||||
5,79,22,34,8,4,4,40,22,24,28,9,13,3,34,27,9,16,39,16,39,13,2,4,3,41,26,10,4,
|
||||
33,4,7,12,5,6,3,10,30,8,21,16,58,19,9,0,47,7,13,11,19,15,7,53,57,2,13,28,22,
|
||||
3,16,9,25,33,12,40,7,12,64,7,14,24,44,9,2,14,11,2,58,1,26,30,11,9,5,24,7,9,
|
||||
94,2,10,21,5,5,4,5,6,179,9,18,2,7,13,31,41,17,4,36,3,21,6,26,8,15,18,44,27,
|
||||
11,9,25,7,0,14,2,12,20,23,13,2,163,9,5,15,65,2,14,6,8,98,11,15,14,34,2,3,10,
|
||||
22,9,92,7,10,32,67,13,3,4,35,8,2,1,5,0,26,381,7,27,8,2,16,93,4,19,5,8,25,9,
|
||||
31,14,4,21,5,3,9,22,56,4,18,3,11,18,6,4,3,40,12,16,110,8,35,14,1,18,40,9,12,
|
||||
14,3,11,7,57,13,18,116,53,19,22,7,16,11,5,8,21,16,1,75,21,20,1,28,2,6,1,7,
|
||||
19,38,5,6,9,9,4,1,7,55,36,62,5,4,4,24,15,1,12,35,48,20,5,17,1,5,26,15,4,54,
|
||||
13,5,5,15,5,19,32,29,31,7,6,40,7,80,11,18,8,128,48,6,12,84,13,4,7,2,13,9,16,
|
||||
17,3,254,1,4,181,8,44,7,6,24,27,9,23,14,34,16,22,25,10,3,3,4,4,12,2,12,6,7,
|
||||
13,58,13,6,11,19,53,11,66,18,19,10,4,13,2,5,49,58,1,67,7,21,64,14,11,14,8,3,
|
||||
26,33,91,31,20,7,9,42,39,4,3,55,11,10,0,7,4,75,8,12,0,27,3,8,9,0,12,12,23,
|
||||
28,23,20,4,13,30,2,22,20,19,30,6,22,2,6,4,24,7,19,55,86,5,33,2,161,6,7,1,62,
|
||||
13,3,72,12,12,9,7,12,10,5,10,29,1,5,22,13,13,5,2,12,3,7,14,18,2,3,46,21,17,
|
||||
15,19,3,27,5,16,45,31,10,8,17,18,18,3,7,24,6,55,9,3,6,12,10,12,8,91,9,4,4,4,
|
||||
27,29,16,5,7,22,43,28,11,14,8,11,28,109,55,71,40,3,8,22,26,15,44,3,25,29,5,
|
||||
3,32,17,12,3,29,27,25,15,11,8,40,39,38,17,3,9,11,2,32,11,6,20,48,75,27,3,7,
|
||||
54,12,95,12,7,24,23,2,13,8,15,16,5,12,4,17,7,19,88,2,6,13,115,45,12,21,2,86,
|
||||
74,9,7,5,16,32,16,2,21,18,6,34,5,18,260,7,12,16,44,19,92,31,7,8,2,9,0,0,15,
|
||||
8,38,4,8,20,18,2,83,3,3,4,9,5,3,10,3,5,29,15,7,11,8,48,17,23,2,17,4,11,22,
|
||||
21,64,8,8,4,19,95,0,17,28,9,11,20,71,5,11,18,12,13,45,49,4,1,33,32,23,13,5,
|
||||
52,2,2,16,3,4,7,12,2,1,12,6,24,1,22,155,21,3,45,4,12,44,26,5,40,36,9,9,8,20,
|
||||
35,31,3,2,32,50,10,8,37,2,75,35,22,15,192,8,11,23,1,4,29,6,8,8,5,12,18,32,4,
|
||||
7,12,2,0,0,9,5,48,11,35,3,1,123,6,29,8,11,8,23,51,16,6,63,12,2,5,4,14,2,15,
|
||||
7,14,3,2,7,17,32,8,8,10,1,23,62,2,49,6,49,47,23,3,20,7,11,39,10,24,6,15,5,5,
|
||||
11,8,16,36,8,13,20,3,10,44,7,52,7,10,36,6,15,10,5,11,4,14,19,17,10,12,3,6,
|
||||
23,4,13,94,70,7,36,7,38,7,28,8,4,15,3,19,4,33,39,21,109,4,80,6,40,4,432,4,4,
|
||||
7,8,3,31,8,28,37,34,10,2,21,5,22,0,7,36,14,12,6,24,1,21,5,9,2,29,20,54,113,
|
||||
13,31,39,27,6,0,27,4,5,2,43,7,8,57,8,62,7,9,12,22,90,30,6,19,7,10,20,6,5,58,
|
||||
32,30,41,4,10,25,13,3,8,7,10,2,9,6,151,44,16,12,16,20,8,3,18,11,17,4,10,45,
|
||||
15,8,56,38,52,25,40,14,4,17,15,8,2,19,7,8,26,30,2,3,180,8,26,17,38,35,5,16,
|
||||
28,5,15,56,13,14,18,9,15,83,27,3,9,4,11,8,27,27,44,10,12,8,3,48,14,7,9,4,4,
|
||||
8,4,5,9,122,8,14,12,19,17,21,4,29,63,21,17,10,12,18,47,10,10,53,4,18,16,4,8,
|
||||
118,9,5,12,9,11,9,3,12,32,3,23,2,15,3,3,30,3,17,235,15,22,9,299,14,17,1,5,
|
||||
16,8,3,7,3,13,2,7,6,4,8,66,2,13,6,15,16,47,3,36,5,7,10,24,1,9,9,8,13,16,26,
|
||||
12,7,24,21,18,49,23,39,10,41,4,13,4,27,11,12,12,19,4,147,8,10,9,40,21,2,83,
|
||||
10,5,6,11,25,9,50,57,40,12,12,21,1,3,24,23,9,3,9,13,2,3,12,57,8,11,13,15,26,
|
||||
15,10,47,36,4,25,1,5,8,5,4,0,12,49,5,19,4,6,16,14,6,10,69,10,33,29,7,8,61,
|
||||
12,4,0,3,7,6,3,16,29,27,38,4,21,0,24,3,2,1,19,16,22,2,8,138,11,7,7,3,12,22,
|
||||
3,16,5,7,3,53,9,10,32,14,5,7,3,6,22,9,59,26,8,7,58,5,16,11,55,7,4,11,146,91,
|
||||
8,13,18,14,6,8,8,31,26,22,6,11,30,11,30,15,18,31,3,48,17,7,6,4,9,2,25,3,35,
|
||||
13,13,7,8,4,31,10,8,10,4,3,45,10,23,2,7,259,17,21,13,14,3,26,3,8,27,4,18,9,
|
||||
66,7,12,5,8,17,4,23,55,41,51,2,32,26,66,4,21,14,12,65,16,22,17,5,14,2,29,24,
|
||||
7,3,36,2,43,53,86,5,28,4,58,13,49,121,6,2,73,2,1,47,4,2,27,10,35,28,27,10,
|
||||
17,10,56,7,10,14,28,20,24,40,7,4,7,3,10,11,32,6,6,3,15,11,54,573,2,3,6,2,3,
|
||||
14,64,4,16,12,16,42,10,26,4,6,11,69,18,27,2,2,17,22,9,13,22,11,6,1,15,49,3,
|
||||
14,1
|
||||
},
|
||||
|
||||
{
|
||||
11,11,11,15,47,1,3,1,23,5,8,18,3,23,15,21,1,7,19,10,26,1,17,11,31,21,41,18,
|
||||
34,4,9,58,19,3,3,36,5,18,13,3,14,4,9,10,4,19,56,15,3,5,3,11,27,9,4,10,13,4,
|
||||
11,6,9,2,18,3,10,19,11,4,53,4,2,2,3,4,58,16,3,0,5,30,2,11,93,10,2,14,10,6,2,
|
||||
115,2,25,16,22,38,101,4,18,13,2,145,51,45,15,14,15,13,20,7,24,5,13,14,30,40,
|
||||
10,4,107,12,24,14,39,12,6,13,20,7,7,11,5,18,18,45,22,6,39,3,2,1,51,9,11,4,
|
||||
13,9,38,44,8,11,9,15,19,9,23,17,17,17,13,9,9,1,10,4,18,6,2,9,5,27,32,72,8,
|
||||
37,9,4,10,30,17,20,15,17,66,10,4,73,35,37,6,4,16,117,45,13,4,75,5,24,65,10,
|
||||
4,9,4,13,46,5,26,29,10,4,4,52,3,13,18,63,6,14,9,24,277,9,88,2,48,27,123,14,
|
||||
61,7,5,10,8,7,90,3,10,3,3,48,17,13,10,18,33,2,19,36,6,21,1,16,12,5,6,2,16,
|
||||
15,29,88,28,2,15,6,11,4,6,11,3,3,4,18,9,53,5,4,3,33,8,9,8,6,7,36,9,62,14,2,
|
||||
1,10,1,16,7,32,7,23,20,11,10,23,2,1,0,9,16,40,2,81,5,22,8,5,4,37,51,37,10,
|
||||
19,57,11,2,92,31,6,39,10,13,16,8,20,6,9,3,10,18,25,23,12,30,6,2,26,7,64,18,
|
||||
6,30,12,13,27,7,10,5,3,33,24,99,4,23,4,1,27,7,27,49,8,20,16,3,4,13,9,22,67,
|
||||
28,3,10,16,3,2,10,4,8,1,8,19,3,85,6,21,1,9,16,2,30,10,33,12,4,9,3,1,60,38,6,
|
||||
24,32,3,14,3,40,8,34,115,5,9,27,5,96,3,40,6,15,5,8,22,112,5,5,25,17,58,2,7,
|
||||
36,21,52,1,3,95,12,21,4,11,8,59,24,5,21,4,9,15,8,7,21,3,26,5,11,6,7,17,65,
|
||||
14,11,10,2,17,5,12,22,4,4,2,21,8,112,3,34,63,35,2,25,1,2,15,65,23,0,3,5,15,
|
||||
26,27,9,5,48,11,15,4,9,5,33,20,15,1,18,19,11,24,40,10,21,74,6,6,32,30,40,5,
|
||||
4,7,44,10,25,46,16,12,5,40,7,18,5,18,9,12,8,4,25,5,6,36,4,43,8,9,12,35,17,4,
|
||||
8,9,11,27,5,10,17,40,8,12,4,18,9,18,12,20,25,39,42,1,24,13,22,15,7,112,35,3,
|
||||
7,17,33,2,5,5,19,8,4,12,24,14,13,2,1,13,6,5,19,11,7,57,0,19,6,117,48,14,8,
|
||||
10,51,17,12,14,2,5,8,9,15,4,48,53,13,22,4,25,12,11,19,45,5,2,6,54,22,9,15,9,
|
||||
13,2,7,11,29,82,16,46,4,26,14,26,40,22,4,26,6,18,13,4,4,20,3,3,7,12,17,8,9,
|
||||
23,6,20,7,25,23,19,5,15,6,23,15,11,19,11,3,17,59,8,18,41,4,54,23,44,75,13,
|
||||
20,6,11,2,3,1,13,10,3,7,12,3,4,7,8,30,6,6,7,3,32,9,5,28,6,114,42,13,36,27,
|
||||
59,6,93,13,74,8,69,140,3,1,17,48,105,6,11,5,15,1,10,10,14,8,53,0,8,24,60,2,
|
||||
6,35,2,12,32,47,16,17,75,2,5,4,37,28,10,5,9,57,4,59,5,12,13,7,90,5,11,5,24,
|
||||
22,13,30,1,2,10,9,6,19,3,18,47,2,5,7,9,35,15,3,6,1,21,14,14,18,14,9,12,8,73,
|
||||
6,19,3,32,9,14,17,17,5,55,23,6,16,28,3,11,48,4,6,6,6,12,16,30,10,30,27,51,
|
||||
18,29,2,3,15,1,76,0,16,33,4,27,3,62,4,10,2,4,8,15,9,41,26,22,2,4,20,4,49,0,
|
||||
8,1,57,13,12,39,3,63,10,19,34,35,2,7,8,29,72,4,10,0,77,8,6,7,9,15,21,9,4,1,
|
||||
20,23,1,9,18,9,15,36,4,7,6,15,5,7,7,40,2,9,22,2,3,20,4,12,34,13,6,18,15,1,
|
||||
38,20,12,7,16,3,19,85,12,16,18,16,2,17,1,13,8,6,12,15,97,17,12,9,3,21,15,12,
|
||||
23,44,81,26,30,2,5,17,6,6,0,22,42,19,6,19,41,14,36,7,3,56,7,9,3,2,6,9,69,3,
|
||||
15,4,30,28,29,7,9,15,17,17,6,1,6,153,9,33,5,12,14,16,28,3,8,7,14,12,4,6,36,
|
||||
9,24,13,13,4,2,9,15,19,9,53,7,13,4,150,17,9,2,6,12,7,3,5,58,19,58,28,8,14,3,
|
||||
20,3,0,32,56,7,5,4,27,1,68,4,29,13,5,58,2,9,65,41,27,16,15,12,14,2,10,9,24,
|
||||
3,2,9,2,2,3,14,32,10,22,3,13,11,4,6,39,17,0,10,5,5,10,35,16,19,14,1,8,63,19,
|
||||
14,8,56,10,2,12,6,12,6,7,16,2,9,9,12,20,73,25,13,21,17,24,5,32,8,12,25,8,14,
|
||||
16,5,23,3,7,6,3,11,24,6,30,4,21,13,28,4,6,29,15,5,17,6,26,8,15,8,3,7,7,50,
|
||||
11,30,6,2,28,56,16,24,25,23,24,89,31,31,12,7,22,4,10,17,3,3,8,11,13,5,3,27,
|
||||
1,12,1,14,8,10,29,2,5,2,2,20,10,0,31,10,21,1,48,3,5,43,4,5,18,13,5,18,25,34,
|
||||
18,3,5,22,16,3,4,20,3,9,3,25,6,6,44,21,3,12,7,5,42,3,2,14,4,36,5,3,45,51,15,
|
||||
9,11,28,9,7,6,6,12,26,5,14,10,11,42,55,13,21,4,28,6,7,23,27,11,1,41,36,0,32,
|
||||
15,26,2,3,23,32,11,2,15,7,29,26,144,33,20,12,7,21,10,7,11,65,46,10,13,20,32,
|
||||
4,4,5,19,2,19,15,49,41,1,75,10,11,25,1,2,45,11,8,27,18,10,60,28,29,12,30,19,
|
||||
16,4,24,11,19,27,17,49,18,7,40,13,19,22,8,55,12,11,3,6,5,11,8,10,22,5,9,9,
|
||||
25,7,17,7,64,1,24,2,12,17,44,4,12,27,21,11,10,7,47,5,9,13,12,38,27,21,7,29,
|
||||
7,1,17,3,3,5,48,62,10,3,11,17,15,15,6,3,8,10,8,18,19,13,3,9,7,6,44,9,10,4,
|
||||
43,8,6,6,14,20,38,24,2,4,5,5,7,5,9,39,8,44,40,9,19,7,3,15,25,2,37,18,15,9,5,
|
||||
8,32,10,5,18,4,7,46,20,17,23,4,11,16,18,31,11,3,11,1,14,1,25,4,27,13,13,39,
|
||||
14,6,6,35,6,16,13,11,122,21,15,20,24,10,5,152,15,39,5,20,16,9,14,7,53,6,3,8,
|
||||
19,63,32,6,2,3,20,1,19,5,13,42,15,4,6,68,31,46,11,38,10,24,5,5,8,9,12,3,35,
|
||||
46,26,16,2,8,4,74,16,44,4,5,1,16,4,14,23,16,69,15,42,31,14,7,7,6,97,14,40,1,
|
||||
8,7,34,9,39,19,13,15,10,21,18,10,5,15,38,7,5,12,7,20,15,4,11,6,14,5,17,7,39,
|
||||
35,36,18,20,26,22,4,2,36,21,64,0,5,9,10,6,4,1,7,3,1,3,3,4,10,20,90,2,22,48,
|
||||
16,23,2,33,40,1,21,21,17,20,8,8,12,4,83,14,48,4,21,3,9,27,5,11,40,15,9,3,16,
|
||||
17,9,11,4,24,31,17,3,4,2,11,1,8,4,8,6,41,17,4,13,3,7,17,8,27,5,13,6,10,7,13,
|
||||
12,18,13,60,18,3,8,1,12,125,2,7,16,2,11,2,4,7,26,5,9,14,14,16,8,14,7,14,6,9,
|
||||
13,9,6,4,26,35,49,36,55,3,9,6,40,26,23,31,19,41,2,10,31,6,54,5,69,16,7,8,16,
|
||||
1,5,7,4,22,7,7,5,4,48,11,13,3,98,4,11,19,4,2,14,7,34,7,10,3,2,12,7,6,2,5,118
|
||||
},
|
||||
};
|
||||
|
||||
uint8_t data[1<<15];
|
||||
string data_str;
|
||||
void init_data() {
|
||||
static bool initted = false;
|
||||
if (initted) return;
|
||||
initted = true;
|
||||
|
||||
// Repeatability. Kind of.
|
||||
std::srand(42);
|
||||
for (size_t i = 0; i < (sizeof(data)/sizeof(data[0])); ++i) {
|
||||
data[i] = (uint8_t)rand();
|
||||
}
|
||||
|
||||
data_str.assign((char*)data, sizeof(data));
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_SUITE( TBufferBaseTest )
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_GetBuffer ) {
|
||||
init_data();
|
||||
|
||||
for (int d1 = 0; d1 < 3; d1++) {
|
||||
TMemoryBuffer buffer(16);
|
||||
int offset = 0;
|
||||
int index = 0;
|
||||
|
||||
while (offset < 1<<15) {
|
||||
buffer.write(&data[offset], dist[d1][index]);
|
||||
offset += dist[d1][index];
|
||||
index++;
|
||||
}
|
||||
|
||||
string output = buffer.getBufferAsString();
|
||||
BOOST_CHECK_EQUAL(data_str, output);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read ) {
|
||||
init_data();
|
||||
|
||||
for (int d1 = 0; d1 < 3; d1++) {
|
||||
for (int d2 = 0; d2 < 3; d2++) {
|
||||
TMemoryBuffer buffer(16);
|
||||
uint8_t data_out[1<<15];
|
||||
int offset;
|
||||
int index;
|
||||
|
||||
offset = 0;
|
||||
index = 0;
|
||||
while (offset < 1<<15) {
|
||||
buffer.write(&data[offset], dist[d1][index]);
|
||||
offset += dist[d1][index];
|
||||
index++;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
index = 0;
|
||||
while (offset < 1<<15) {
|
||||
unsigned int got = buffer.read(&data_out[offset], dist[d2][index]);
|
||||
BOOST_CHECK_EQUAL(got, dist[d2][index]);
|
||||
offset += dist[d2][index];
|
||||
index++;
|
||||
}
|
||||
|
||||
BOOST_CHECK(!memcmp(data, data_out, sizeof(data)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_ReadString ) {
|
||||
init_data();
|
||||
|
||||
for (int d1 = 0; d1 < 3; d1++) {
|
||||
for (int d2 = 0; d2 < 3; d2++) {
|
||||
TMemoryBuffer buffer(16);
|
||||
string output;
|
||||
int offset;
|
||||
int index;
|
||||
|
||||
offset = 0;
|
||||
index = 0;
|
||||
while (offset < 1<<15) {
|
||||
buffer.write(&data[offset], dist[d1][index]);
|
||||
offset += dist[d1][index];
|
||||
index++;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
index = 0;
|
||||
while (offset < 1<<15) {
|
||||
unsigned int got = buffer.readAppendToString(output, dist[d2][index]);
|
||||
BOOST_CHECK_EQUAL(got, dist[d2][index]);
|
||||
offset += dist[d2][index];
|
||||
index++;
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL(output, data_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read_Multi1 ) {
|
||||
init_data();
|
||||
|
||||
// Do shorter writes and reads so we don't align to power-of-two boundaries.
|
||||
|
||||
for (int d1 = 0; d1 < 3; d1++) {
|
||||
for (int d2 = 0; d2 < 3; d2++) {
|
||||
TMemoryBuffer buffer(16);
|
||||
uint8_t data_out[1<<15];
|
||||
int offset;
|
||||
int index;
|
||||
|
||||
for (int iter = 0; iter < 6; iter++) {
|
||||
offset = 0;
|
||||
index = 0;
|
||||
while (offset < (1<<15)-42) {
|
||||
buffer.write(&data[offset], dist[d1][index]);
|
||||
offset += dist[d1][index];
|
||||
index++;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
index = 0;
|
||||
while (offset < (1<<15)-42) {
|
||||
buffer.read(&data_out[offset], dist[d2][index]);
|
||||
offset += dist[d2][index];
|
||||
index++;
|
||||
}
|
||||
|
||||
BOOST_CHECK(!memcmp(data, data_out, (1<<15)-42));
|
||||
|
||||
// Pull out the extra data.
|
||||
buffer.read(data_out, 42);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read_Multi2 ) {
|
||||
init_data();
|
||||
|
||||
// Do shorter writes and reads so we don't align to power-of-two boundaries.
|
||||
// Pull the buffer out of the loop so its state gets worked harder.
|
||||
TMemoryBuffer buffer(16);
|
||||
|
||||
for (int d1 = 0; d1 < 3; d1++) {
|
||||
for (int d2 = 0; d2 < 3; d2++) {
|
||||
uint8_t data_out[1<<15];
|
||||
int offset;
|
||||
int index;
|
||||
|
||||
for (int iter = 0; iter < 6; iter++) {
|
||||
offset = 0;
|
||||
index = 0;
|
||||
while (offset < (1<<15)-42) {
|
||||
buffer.write(&data[offset], dist[d1][index]);
|
||||
offset += dist[d1][index];
|
||||
index++;
|
||||
}
|
||||
|
||||
offset = 0;
|
||||
index = 0;
|
||||
while (offset < (1<<15)-42) {
|
||||
buffer.read(&data_out[offset], dist[d2][index]);
|
||||
offset += dist[d2][index];
|
||||
index++;
|
||||
}
|
||||
|
||||
BOOST_CHECK(!memcmp(data, data_out, (1<<15)-42));
|
||||
|
||||
// Pull out the extra data.
|
||||
buffer.read(data_out, 42);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_MemoryBuffer_Write_Read_Incomplete ) {
|
||||
init_data();
|
||||
|
||||
// Do shorter writes and reads so we don't align to power-of-two boundaries.
|
||||
// Pull the buffer out of the loop so its state gets worked harder.
|
||||
|
||||
for (int d1 = 0; d1 < 3; d1++) {
|
||||
for (int d2 = 0; d2 < 3; d2++) {
|
||||
TMemoryBuffer buffer(16);
|
||||
uint8_t data_out[1<<13];
|
||||
|
||||
int write_offset = 0;
|
||||
int write_index = 0;
|
||||
unsigned int to_write = (1<<14)-42;
|
||||
while (to_write > 0) {
|
||||
int write_amt = (std::min)(dist[d1][write_index], to_write);
|
||||
buffer.write(&data[write_offset], write_amt);
|
||||
write_offset += write_amt;
|
||||
write_index++;
|
||||
to_write -= write_amt;
|
||||
}
|
||||
|
||||
int read_offset = 0;
|
||||
int read_index = 0;
|
||||
unsigned int to_read = (1<<13)-42;
|
||||
while (to_read > 0) {
|
||||
int read_amt = (std::min)(dist[d2][read_index], to_read);
|
||||
int got = buffer.read(&data_out[read_offset], read_amt);
|
||||
BOOST_CHECK_EQUAL(got, read_amt);
|
||||
read_offset += read_amt;
|
||||
read_index++;
|
||||
to_read -= read_amt;
|
||||
}
|
||||
|
||||
BOOST_CHECK(!memcmp(data, data_out, (1<<13)-42));
|
||||
|
||||
int second_offset = write_offset;
|
||||
int second_index = write_index-1;
|
||||
unsigned int to_second = (1<<14)+42;
|
||||
while (to_second > 0) {
|
||||
int second_amt = (std::min)(dist[d1][second_index], to_second);
|
||||
//printf("%d\n", second_amt);
|
||||
buffer.write(&data[second_offset], second_amt);
|
||||
second_offset += second_amt;
|
||||
second_index++;
|
||||
to_second -= second_amt;
|
||||
}
|
||||
|
||||
string output = buffer.getBufferAsString();
|
||||
BOOST_CHECK_EQUAL(data_str.substr((1<<13)-42), output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_BufferedTransport_Write ) {
|
||||
init_data();
|
||||
|
||||
int sizes[] = {
|
||||
12, 15, 16, 17, 20,
|
||||
501, 512, 523,
|
||||
2000, 2048, 2096,
|
||||
1<<14, 1<<17,
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof (sizes) / sizeof (sizes[0]); i++) {
|
||||
int size = sizes[i];
|
||||
for (int d1 = 0; d1 < 3; d1++) {
|
||||
shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(16));
|
||||
TBufferedTransport trans(buffer, size);
|
||||
|
||||
int offset = 0;
|
||||
int index = 0;
|
||||
while (offset < 1<<15) {
|
||||
trans.write(&data[offset], dist[d1][index]);
|
||||
offset += dist[d1][index];
|
||||
index++;
|
||||
}
|
||||
trans.flush();
|
||||
|
||||
string output = buffer->getBufferAsString();
|
||||
BOOST_CHECK_EQUAL(data_str, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_BufferedTransport_Read_Full ) {
|
||||
init_data();
|
||||
|
||||
int sizes[] = {
|
||||
12, 15, 16, 17, 20,
|
||||
501, 512, 523,
|
||||
2000, 2048, 2096,
|
||||
1<<14, 1<<17,
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof (sizes) / sizeof (sizes[0]); i++) {
|
||||
int size = sizes[i];
|
||||
for (int d1 = 0; d1 < 3; d1++) {
|
||||
shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(data, sizeof(data)));
|
||||
TBufferedTransport trans(buffer, size);
|
||||
uint8_t data_out[1<<15];
|
||||
|
||||
int offset = 0;
|
||||
int index = 0;
|
||||
while (offset < 1<<15) {
|
||||
// Note: this doesn't work with "read" because TBufferedTransport
|
||||
// doesn't try loop over reads, so we get short reads. We don't
|
||||
// check the return value, so that messes us up.
|
||||
trans.readAll(&data_out[offset], dist[d1][index]);
|
||||
offset += dist[d1][index];
|
||||
index++;
|
||||
}
|
||||
|
||||
BOOST_CHECK(!memcmp(data, data_out, sizeof(data)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_BufferedTransport_Read_Short ) {
|
||||
init_data();
|
||||
|
||||
int sizes[] = {
|
||||
12, 15, 16, 17, 20,
|
||||
501, 512, 523,
|
||||
2000, 2048, 2096,
|
||||
1<<14, 1<<17,
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof (sizes) / sizeof (sizes[0]); i++) {
|
||||
int size = sizes[i];
|
||||
for (int d1 = 0; d1 < 3; d1++) {
|
||||
shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(data, sizeof(data)));
|
||||
shared_ptr<TShortReadTransport> tshort(new TShortReadTransport(buffer, 0.125));
|
||||
TBufferedTransport trans(buffer, size);
|
||||
uint8_t data_out[1<<15];
|
||||
|
||||
int offset = 0;
|
||||
int index = 0;
|
||||
while (offset < 1<<15) {
|
||||
// Note: this doesn't work with "read" because TBufferedTransport
|
||||
// doesn't try loop over reads, so we get short reads. We don't
|
||||
// check the return value, so that messes us up.
|
||||
trans.readAll(&data_out[offset], dist[d1][index]);
|
||||
offset += dist[d1][index];
|
||||
index++;
|
||||
}
|
||||
|
||||
BOOST_CHECK(!memcmp(data, data_out, sizeof(data)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_FramedTransport_Write ) {
|
||||
init_data();
|
||||
|
||||
int sizes[] = {
|
||||
12, 15, 16, 17, 20,
|
||||
501, 512, 523,
|
||||
2000, 2048, 2096,
|
||||
1<<14, 1<<17,
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof (sizes) / sizeof (sizes[0]); i++) {
|
||||
int size = sizes[i];
|
||||
for (int d1 = 0; d1 < 3; d1++) {
|
||||
shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(16));
|
||||
TFramedTransport trans(buffer, size);
|
||||
|
||||
int offset = 0;
|
||||
int index = 0;
|
||||
while (offset < 1<<15) {
|
||||
trans.write(&data[offset], dist[d1][index]);
|
||||
offset += dist[d1][index];
|
||||
index++;
|
||||
}
|
||||
trans.flush();
|
||||
|
||||
int32_t frame_size = -1;
|
||||
buffer->read(reinterpret_cast<uint8_t*>(&frame_size), sizeof(frame_size));
|
||||
frame_size = (int32_t)ntohl((uint32_t)frame_size);
|
||||
BOOST_CHECK_EQUAL(frame_size, 1<<15);
|
||||
BOOST_CHECK_EQUAL(data_str.size(), (unsigned int)frame_size);
|
||||
string output = buffer->getBufferAsString();
|
||||
BOOST_CHECK_EQUAL(data_str, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_FramedTransport_Read ) {
|
||||
init_data();
|
||||
|
||||
for (int d1 = 0; d1 < 3; d1++) {
|
||||
uint8_t data_out[1<<15];
|
||||
shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
|
||||
TFramedTransport trans(buffer);
|
||||
int32_t length = sizeof(data);
|
||||
length = (int32_t)htonl((uint32_t)length);
|
||||
buffer->write(reinterpret_cast<uint8_t*>(&length), sizeof(length));
|
||||
buffer->write(data, sizeof(data));
|
||||
|
||||
int offset = 0;
|
||||
int index = 0;
|
||||
while (offset < 1<<15) {
|
||||
// This should work with read because we have one huge frame.
|
||||
trans.read(&data_out[offset], dist[d1][index]);
|
||||
offset += dist[d1][index];
|
||||
index++;
|
||||
}
|
||||
|
||||
BOOST_CHECK(!memcmp(data, data_out, sizeof(data)));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_FramedTransport_Write_Read ) {
|
||||
init_data();
|
||||
|
||||
int sizes[] = {
|
||||
12, 15, 16, 17, 20,
|
||||
501, 512, 523,
|
||||
2000, 2048, 2096,
|
||||
1<<14, 1<<17,
|
||||
};
|
||||
|
||||
int probs[] = { 1, 2, 4, 8, 16, 32, };
|
||||
|
||||
for (size_t i = 0; i < sizeof (sizes) / sizeof (sizes[0]); i++) {
|
||||
int size = sizes[i];
|
||||
for (size_t j = 0; j < sizeof (probs) / sizeof (probs[0]); j++) {
|
||||
int prob = probs[j];
|
||||
for (int d1 = 0; d1 < 3; d1++) {
|
||||
shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(16));
|
||||
TFramedTransport trans(buffer, size);
|
||||
uint8_t data_out[1<<15];
|
||||
std::vector<int> flush_sizes;
|
||||
|
||||
int write_offset = 0;
|
||||
int write_index = 0;
|
||||
int flush_size = 0;
|
||||
while (write_offset < 1<<15) {
|
||||
trans.write(&data[write_offset], dist[d1][write_index]);
|
||||
write_offset += dist[d1][write_index];
|
||||
flush_size += dist[d1][write_index];
|
||||
write_index++;
|
||||
if (flush_size > 0 && rand()%prob == 0) {
|
||||
flush_sizes.push_back(flush_size);
|
||||
flush_size = 0;
|
||||
trans.flush();
|
||||
}
|
||||
}
|
||||
if (flush_size != 0) {
|
||||
flush_sizes.push_back(flush_size);
|
||||
flush_size = 0;
|
||||
trans.flush();
|
||||
}
|
||||
|
||||
int read_offset = 0;
|
||||
int read_index = 0;
|
||||
|
||||
for (unsigned int k = 0; k < flush_sizes.size(); k++) {
|
||||
int fsize = flush_sizes[k];
|
||||
// We are exploiting an implementation detail of TFramedTransport.
|
||||
// The read buffer starts empty and it will never do more than one
|
||||
// readFrame per read, so we should always get exactly one frame.
|
||||
int got = trans.read(&data_out[read_offset], 1<<15);
|
||||
BOOST_CHECK_EQUAL(got, fsize);
|
||||
read_offset += got;
|
||||
read_index++;
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL((unsigned int)read_offset, sizeof(data));
|
||||
BOOST_CHECK(!memcmp(data, data_out, sizeof(data)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( test_FramedTransport_Empty_Flush ) {
|
||||
init_data();
|
||||
|
||||
string output1("\x00\x00\x00\x01""a", 5);
|
||||
string output2("\x00\x00\x00\x01""a\x00\x00\x00\x02""bc", 11);
|
||||
|
||||
shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer());
|
||||
TFramedTransport trans(buffer);
|
||||
|
||||
BOOST_CHECK_EQUAL(buffer->getBufferAsString(), "");
|
||||
trans.flush();
|
||||
BOOST_CHECK_EQUAL(buffer->getBufferAsString(), "");
|
||||
trans.flush();
|
||||
trans.flush();
|
||||
BOOST_CHECK_EQUAL(buffer->getBufferAsString(), "");
|
||||
trans.write((const uint8_t*)"a", 1);
|
||||
BOOST_CHECK_EQUAL(buffer->getBufferAsString(), "");
|
||||
trans.flush();
|
||||
BOOST_CHECK_EQUAL(buffer->getBufferAsString(), output1);
|
||||
trans.flush();
|
||||
trans.flush();
|
||||
BOOST_CHECK_EQUAL(buffer->getBufferAsString(), output1);
|
||||
trans.write((const uint8_t*)"bc", 2);
|
||||
BOOST_CHECK_EQUAL(buffer->getBufferAsString(), output1);
|
||||
trans.flush();
|
||||
BOOST_CHECK_EQUAL(buffer->getBufferAsString(), output2);
|
||||
trans.flush();
|
||||
trans.flush();
|
||||
BOOST_CHECK_EQUAL(buffer->getBufferAsString(), output2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
50
vendor/git.apache.org/thrift.git/lib/cpp/test/TFDTransportTest.cpp
generated
vendored
Normal file
50
vendor/git.apache.org/thrift.git/lib/cpp/test/TFDTransportTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <cstdlib>
|
||||
#include <stdexcept>
|
||||
#include <thrift/Thrift.h>
|
||||
#include <thrift/transport/TFDTransport.h>
|
||||
|
||||
#define BOOST_TEST_MODULE TFDTransportTest
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
// Disabled on MSVC because the RTL asserts on an invalid file descriptor
|
||||
// in both debug and release mode; at least in MSVCR100 (Visual Studio 2010)
|
||||
#if !defined(WIN32)
|
||||
|
||||
using apache::thrift::transport::TTransportException;
|
||||
using apache::thrift::transport::TFDTransport;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_tfdtransport_1) {
|
||||
BOOST_CHECK_NO_THROW(TFDTransport t(256, TFDTransport::CLOSE_ON_DESTROY));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_tfdtransport_2) {
|
||||
TFDTransport t(256, TFDTransport::CLOSE_ON_DESTROY);
|
||||
BOOST_CHECK_THROW(t.close(), TTransportException);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_tfdtransport_dummy) {
|
||||
BOOST_CHECK(true);
|
||||
}
|
||||
|
||||
#endif
|
417
vendor/git.apache.org/thrift.git/lib/cpp/test/TFileTransportTest.cpp
generated
vendored
Normal file
417
vendor/git.apache.org/thrift.git/lib/cpp/test/TFileTransportTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,417 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 _GNU_SOURCE
|
||||
#define _GNU_SOURCE // needed for getopt_long
|
||||
#endif
|
||||
|
||||
#include <thrift/thrift-config.h>
|
||||
|
||||
#ifdef HAVE_SYS_TIME_H
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <getopt.h>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <thrift/transport/TFileTransport.h>
|
||||
|
||||
#ifdef __MINGW32__
|
||||
#include <io.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys\stat.h>
|
||||
#endif
|
||||
|
||||
using namespace apache::thrift::transport;
|
||||
|
||||
/**************************************************************************
|
||||
* Global state
|
||||
**************************************************************************/
|
||||
|
||||
static const char* tmp_dir = "/tmp";
|
||||
|
||||
class FsyncLog;
|
||||
FsyncLog* fsync_log;
|
||||
|
||||
/**************************************************************************
|
||||
* Helper code
|
||||
**************************************************************************/
|
||||
|
||||
// Provide BOOST_WARN_LT() and BOOST_WARN_GT(), in case we're compiled
|
||||
// with an older version of boost
|
||||
#ifndef BOOST_WARN_LT
|
||||
#define BOOST_WARN_CMP(a, b, op, check_fn) \
|
||||
check_fn((a)op(b), \
|
||||
"check " BOOST_STRINGIZE(a) " " BOOST_STRINGIZE(op) " " BOOST_STRINGIZE( \
|
||||
b) " failed: " BOOST_STRINGIZE(a) "=" \
|
||||
<< (a) << " " BOOST_STRINGIZE(b) "=" << (b))
|
||||
|
||||
#define BOOST_WARN_LT(a, b) BOOST_WARN_CMP(a, b, <, BOOST_WARN_MESSAGE)
|
||||
#define BOOST_WARN_GT(a, b) BOOST_WARN_CMP(a, b, >, BOOST_WARN_MESSAGE)
|
||||
#define BOOST_WARN_LT(a, b) BOOST_WARN_CMP(a, b, <, BOOST_WARN_MESSAGE)
|
||||
#endif // BOOST_WARN_LT
|
||||
|
||||
/**
|
||||
* Class to record calls to fsync
|
||||
*/
|
||||
class FsyncLog {
|
||||
public:
|
||||
struct FsyncCall {
|
||||
struct timeval time;
|
||||
int fd;
|
||||
};
|
||||
typedef std::list<FsyncCall> CallList;
|
||||
|
||||
FsyncLog() {}
|
||||
|
||||
void fsync(int fd) {
|
||||
(void)fd;
|
||||
FsyncCall call;
|
||||
gettimeofday(&call.time, NULL);
|
||||
calls_.push_back(call);
|
||||
}
|
||||
|
||||
const CallList* getCalls() const { return &calls_; }
|
||||
|
||||
private:
|
||||
CallList calls_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class to clean up temporary files
|
||||
*/
|
||||
class TempFile {
|
||||
public:
|
||||
TempFile(const char* directory, const char* prefix) {
|
||||
#ifdef __MINGW32__
|
||||
size_t path_len = strlen(prefix) + 8;
|
||||
path_ = new char[path_len];
|
||||
snprintf(path_, path_len, "%sXXXXXX", prefix);
|
||||
if (_mktemp_s(path_,path_len) == 0) {
|
||||
fd_ = open(path_,O_CREAT | O_RDWR | O_BINARY,S_IREAD | S_IWRITE);
|
||||
if (fd_ < 0) {
|
||||
throw apache::thrift::TException("_mktemp_s() failed");
|
||||
}
|
||||
} else {
|
||||
throw apache::thrift::TException("_mktemp_s() failed");
|
||||
}
|
||||
#else
|
||||
size_t path_len = strlen(directory) + strlen(prefix) + 8;
|
||||
path_ = new char[path_len];
|
||||
snprintf(path_, path_len, "%s/%sXXXXXX", directory, prefix);
|
||||
|
||||
fd_ = mkstemp(path_);
|
||||
if (fd_ < 0) {
|
||||
throw apache::thrift::TException("mkstemp() failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
~TempFile() {
|
||||
unlink();
|
||||
close();
|
||||
}
|
||||
|
||||
const char* getPath() const { return path_; }
|
||||
|
||||
int getFD() const { return fd_; }
|
||||
|
||||
void unlink() {
|
||||
if (path_) {
|
||||
::unlink(path_);
|
||||
delete[] path_;
|
||||
path_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void close() {
|
||||
if (fd_ < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
::close(fd_);
|
||||
fd_ = -1;
|
||||
}
|
||||
|
||||
private:
|
||||
char* path_;
|
||||
int fd_;
|
||||
};
|
||||
|
||||
// Use our own version of fsync() for testing.
|
||||
// This returns immediately, so timing in test_destructor() isn't affected by
|
||||
// waiting on the actual filesystem.
|
||||
extern "C" int fsync(int fd) {
|
||||
if (fsync_log) {
|
||||
fsync_log->fsync(fd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int time_diff(const struct timeval* t1, const struct timeval* t2) {
|
||||
return (t2->tv_usec - t1->tv_usec) + (t2->tv_sec - t1->tv_sec) * 1000000;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* Test cases
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Make sure the TFileTransport destructor exits "quickly".
|
||||
*
|
||||
* Previous versions had a bug causing the writer thread not to exit
|
||||
* right away.
|
||||
*
|
||||
* It's kind of lame that we just check to see how long the destructor takes in
|
||||
* wall-clock time. This could result in false failures on slower systems, or
|
||||
* on heavily loaded machines.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(test_destructor) {
|
||||
TempFile f(tmp_dir, "thrift.TFileTransportTest.");
|
||||
|
||||
unsigned int const NUM_ITERATIONS = 1000;
|
||||
|
||||
unsigned int num_over = 0;
|
||||
for (unsigned int n = 0; n < NUM_ITERATIONS; ++n) {
|
||||
BOOST_CHECK_EQUAL(0, ftruncate(f.getFD(), 0));
|
||||
|
||||
TFileTransport* transport = new TFileTransport(f.getPath());
|
||||
|
||||
// write something so that the writer thread gets started
|
||||
transport->write(reinterpret_cast<const uint8_t*>("foo"), 3);
|
||||
|
||||
// Every other iteration, also call flush(), just in case that potentially
|
||||
// has any effect on how the writer thread wakes up.
|
||||
if (n & 0x1) {
|
||||
transport->flush();
|
||||
}
|
||||
|
||||
/*
|
||||
* Time the call to the destructor
|
||||
*/
|
||||
struct timeval start;
|
||||
struct timeval end;
|
||||
|
||||
gettimeofday(&start, NULL);
|
||||
delete transport;
|
||||
gettimeofday(&end, NULL);
|
||||
|
||||
int delta = time_diff(&start, &end);
|
||||
|
||||
// If any attempt takes more than 500ms, treat that as a failure.
|
||||
// Treat this as a fatal failure, so we'll return now instead of
|
||||
// looping over a very slow operation.
|
||||
BOOST_WARN_LT(delta, 500000);
|
||||
|
||||
// Normally, it takes less than 100ms on my dev box.
|
||||
// However, if the box is heavily loaded, some of the test runs
|
||||
// take longer, since we're just waiting for our turn on the CPU.
|
||||
if (delta > 100000) {
|
||||
++num_over;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure fewer than 10% of the runs took longer than 1000us
|
||||
BOOST_WARN(num_over < (NUM_ITERATIONS / 10));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure setFlushMaxUs() is honored.
|
||||
*/
|
||||
void test_flush_max_us_impl(uint32_t flush_us, uint32_t write_us, uint32_t test_us) {
|
||||
// TFileTransport only calls fsync() if data has been written,
|
||||
// so make sure the write interval is smaller than the flush interval.
|
||||
BOOST_WARN(write_us < flush_us);
|
||||
|
||||
TempFile f(tmp_dir, "thrift.TFileTransportTest.");
|
||||
|
||||
// Record calls to fsync()
|
||||
FsyncLog log;
|
||||
fsync_log = &log;
|
||||
|
||||
TFileTransport* transport = new TFileTransport(f.getPath());
|
||||
// Don't flush because of # of bytes written
|
||||
transport->setFlushMaxBytes(0xffffffff);
|
||||
uint8_t buf[] = "a";
|
||||
uint32_t buflen = sizeof(buf);
|
||||
|
||||
// Set the flush interval
|
||||
transport->setFlushMaxUs(flush_us);
|
||||
|
||||
// Make one call to write, to start the writer thread now.
|
||||
// (If we just let the thread get created during our test loop,
|
||||
// the thread creation sometimes takes long enough to make the first
|
||||
// fsync interval fail the check.)
|
||||
transport->write(buf, buflen);
|
||||
|
||||
// Add one entry to the fsync log, just to mark the start time
|
||||
log.fsync(-1);
|
||||
|
||||
// Loop doing write(), sleep(), ...
|
||||
uint32_t total_time = 0;
|
||||
while (true) {
|
||||
transport->write(buf, buflen);
|
||||
if (total_time > test_us) {
|
||||
break;
|
||||
}
|
||||
usleep(write_us);
|
||||
total_time += write_us;
|
||||
}
|
||||
|
||||
delete transport;
|
||||
|
||||
// Stop logging new fsync() calls
|
||||
fsync_log = NULL;
|
||||
|
||||
// Examine the fsync() log
|
||||
//
|
||||
// TFileTransport uses pthread_cond_timedwait(), which only has millisecond
|
||||
// resolution. In my testing, it normally wakes up about 1 millisecond late.
|
||||
// However, sometimes it takes a bit longer. Allow 5ms leeway.
|
||||
int max_allowed_delta = flush_us + 5000;
|
||||
|
||||
const FsyncLog::CallList* calls = log.getCalls();
|
||||
// We added 1 fsync call above.
|
||||
// Make sure TFileTransport called fsync at least once
|
||||
BOOST_WARN_GE(calls->size(), static_cast<FsyncLog::CallList::size_type>(1));
|
||||
|
||||
const struct timeval* prev_time = NULL;
|
||||
for (FsyncLog::CallList::const_iterator it = calls->begin(); it != calls->end(); ++it) {
|
||||
if (prev_time) {
|
||||
int delta = time_diff(prev_time, &it->time);
|
||||
BOOST_WARN_LT(delta, max_allowed_delta);
|
||||
}
|
||||
prev_time = &it->time;
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_flush_max_us1) {
|
||||
// fsync every 10ms, write every 5ms, for 500ms
|
||||
test_flush_max_us_impl(10000, 5000, 500000);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_flush_max_us2) {
|
||||
// fsync every 50ms, write every 20ms, for 500ms
|
||||
test_flush_max_us_impl(50000, 20000, 500000);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_flush_max_us3) {
|
||||
// fsync every 400ms, write every 300ms, for 1s
|
||||
test_flush_max_us_impl(400000, 300000, 1000000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure flush() is fast when there is nothing to do.
|
||||
*
|
||||
* TFileTransport used to have a bug where flush() would wait for the fsync
|
||||
* timeout to expire.
|
||||
*/
|
||||
BOOST_AUTO_TEST_CASE(test_noop_flush) {
|
||||
TempFile f(tmp_dir, "thrift.TFileTransportTest.");
|
||||
TFileTransport transport(f.getPath());
|
||||
|
||||
// Write something to start the writer thread.
|
||||
uint8_t buf[] = "a";
|
||||
transport.write(buf, 1);
|
||||
|
||||
struct timeval start;
|
||||
gettimeofday(&start, NULL);
|
||||
|
||||
for (unsigned int n = 0; n < 10; ++n) {
|
||||
transport.flush();
|
||||
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
|
||||
// Fail if at any point we've been running for longer than half a second.
|
||||
// (With the buggy code, TFileTransport used to take 3 seconds per flush())
|
||||
//
|
||||
// Use a fatal fail so we break out early, rather than continuing to make
|
||||
// many more slow flush() calls.
|
||||
int delta = time_diff(&start, &now);
|
||||
BOOST_WARN_LT(delta, 2000000);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
* General Initialization
|
||||
**************************************************************************/
|
||||
|
||||
void print_usage(FILE* f, const char* argv0) {
|
||||
fprintf(f, "Usage: %s [boost_options] [options]\n", argv0);
|
||||
fprintf(f, "Options:\n");
|
||||
fprintf(f, " --tmp-dir=DIR, -t DIR\n");
|
||||
fprintf(f, " --help\n");
|
||||
}
|
||||
|
||||
void parse_args(int argc, char* argv[]) {
|
||||
struct option long_opts[]
|
||||
= {{"help", false, NULL, 'h'}, {"tmp-dir", true, NULL, 't'}, {NULL, 0, NULL, 0}};
|
||||
|
||||
while (true) {
|
||||
optopt = 1;
|
||||
int optchar = getopt_long(argc, argv, "ht:", long_opts, NULL);
|
||||
if (optchar == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (optchar) {
|
||||
case 't':
|
||||
tmp_dir = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
print_usage(stdout, argv[0]);
|
||||
exit(0);
|
||||
case '?':
|
||||
exit(1);
|
||||
default:
|
||||
// Only happens if someone adds another option to the optarg string,
|
||||
// but doesn't update the switch statement to handle it.
|
||||
fprintf(stderr, "unknown option \"-%c\"\n", optchar);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BOOST_TEST_DYN_LINK
|
||||
static int myArgc = 0;
|
||||
static char **myArgv = NULL;
|
||||
|
||||
bool init_unit_test_suite() {
|
||||
boost::unit_test::framework::master_test_suite().p_name.value = "TFileTransportTest";
|
||||
|
||||
// Parse arguments
|
||||
parse_args(myArgc,myArgv);
|
||||
return true;
|
||||
}
|
||||
|
||||
int main( int argc, char* argv[] ) {
|
||||
myArgc = argc;
|
||||
myArgv = argv;
|
||||
return ::boost::unit_test::unit_test_main(&init_unit_test_suite,argc,argv);
|
||||
}
|
||||
#else
|
||||
boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) {
|
||||
boost::unit_test::framework::master_test_suite().p_name.value = "TFileTransportTest";
|
||||
|
||||
// Parse arguments
|
||||
parse_args(argc, argv);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
119
vendor/git.apache.org/thrift.git/lib/cpp/test/TMemoryBufferTest.cpp
generated
vendored
Normal file
119
vendor/git.apache.org/thrift.git/lib/cpp/test/TMemoryBufferTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <boost/test/auto_unit_test.hpp>
|
||||
#include <iostream>
|
||||
#include <climits>
|
||||
#include <vector>
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
#include <thrift/protocol/TBinaryProtocol.h>
|
||||
#include "gen-cpp/ThriftTest_types.h"
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(TMemoryBufferTest)
|
||||
|
||||
using apache::thrift::protocol::TBinaryProtocol;
|
||||
using apache::thrift::transport::TMemoryBuffer;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
using boost::shared_ptr;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using std::string;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_read_write_grow) {
|
||||
// Added to test the fix for THRIFT-1248
|
||||
TMemoryBuffer uut;
|
||||
const int maxSize = 65536;
|
||||
uint8_t verify[maxSize];
|
||||
std::vector<uint8_t> buf;
|
||||
buf.resize(maxSize);
|
||||
|
||||
for (uint32_t i = 0; i < maxSize; ++i) {
|
||||
buf[i] = static_cast<uint8_t>(i);
|
||||
}
|
||||
|
||||
for (uint32_t i = 1; i < maxSize; i *= 2) {
|
||||
uut.write(&buf[0], i);
|
||||
}
|
||||
|
||||
for (uint32_t i = 1; i < maxSize; i *= 2) {
|
||||
uut.read(verify, i);
|
||||
BOOST_CHECK_EQUAL(0, ::memcmp(verify, &buf[0], i));
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_roundtrip) {
|
||||
shared_ptr<TMemoryBuffer> strBuffer(new TMemoryBuffer());
|
||||
shared_ptr<TBinaryProtocol> binaryProtcol(new TBinaryProtocol(strBuffer));
|
||||
|
||||
thrift::test::Xtruct a;
|
||||
a.i32_thing = 10;
|
||||
a.i64_thing = 30;
|
||||
a.string_thing = "holla back a";
|
||||
|
||||
a.write(binaryProtcol.get());
|
||||
std::string serialized = strBuffer->getBufferAsString();
|
||||
|
||||
shared_ptr<TMemoryBuffer> strBuffer2(new TMemoryBuffer());
|
||||
shared_ptr<TBinaryProtocol> binaryProtcol2(new TBinaryProtocol(strBuffer2));
|
||||
|
||||
strBuffer2->resetBuffer((uint8_t*)serialized.data(), static_cast<uint32_t>(serialized.length()));
|
||||
thrift::test::Xtruct a2;
|
||||
a2.read(binaryProtcol2.get());
|
||||
|
||||
BOOST_CHECK(a == a2);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_copy) {
|
||||
string* str1 = new string("abcd1234");
|
||||
const char* data1 = str1->data();
|
||||
TMemoryBuffer buf((uint8_t*)str1->data(),
|
||||
static_cast<uint32_t>(str1->length()),
|
||||
TMemoryBuffer::COPY);
|
||||
delete str1;
|
||||
string* str2 = new string("plsreuse");
|
||||
bool obj_reuse = (str1 == str2);
|
||||
bool dat_reuse = (data1 == str2->data());
|
||||
BOOST_TEST_MESSAGE("Object reuse: " << obj_reuse << " Data reuse: " << dat_reuse
|
||||
<< ((obj_reuse && dat_reuse) ? " YAY!" : ""));
|
||||
delete str2;
|
||||
|
||||
string str3 = "wxyz", str4 = "6789";
|
||||
buf.readAppendToString(str3, 4);
|
||||
buf.readAppendToString(str4, INT_MAX);
|
||||
|
||||
BOOST_CHECK(str3 == "wxyzabcd");
|
||||
BOOST_CHECK(str4 == "67891234");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_exceptions) {
|
||||
char data[] = "foo\0bar";
|
||||
|
||||
TMemoryBuffer buf1((uint8_t*)data, 7, TMemoryBuffer::OBSERVE);
|
||||
string str = buf1.getBufferAsString();
|
||||
BOOST_CHECK(str.length() == 7);
|
||||
|
||||
buf1.resetBuffer();
|
||||
|
||||
BOOST_CHECK_THROW(buf1.write((const uint8_t*)"foo", 3), TTransportException);
|
||||
|
||||
TMemoryBuffer buf2((uint8_t*)data, 7, TMemoryBuffer::COPY);
|
||||
BOOST_CHECK_NO_THROW(buf2.write((const uint8_t*)"bar", 3));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
178
vendor/git.apache.org/thrift.git/lib/cpp/test/TNonblockingServerTest.cpp
generated
vendored
Normal file
178
vendor/git.apache.org/thrift.git/lib/cpp/test/TNonblockingServerTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,178 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE TNonblockingServerTest
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/smart_ptr.hpp>
|
||||
|
||||
#include "thrift/concurrency/Thread.h"
|
||||
#include "thrift/server/TNonblockingServer.h"
|
||||
|
||||
#include "gen-cpp/ParentService.h"
|
||||
|
||||
#include <event.h>
|
||||
|
||||
using namespace apache::thrift;
|
||||
|
||||
struct Handler : public test::ParentServiceIf {
|
||||
void addString(const std::string& s) { strings_.push_back(s); }
|
||||
void getStrings(std::vector<std::string>& _return) { _return = strings_; }
|
||||
std::vector<std::string> strings_;
|
||||
|
||||
// dummy overrides not used in this test
|
||||
int32_t incrementGeneration() { return 0; }
|
||||
int32_t getGeneration() { return 0; }
|
||||
void getDataWait(std::string&, const int32_t) {}
|
||||
void onewayWait() {}
|
||||
void exceptionWait(const std::string&) {}
|
||||
void unexpectedExceptionWait(const std::string&) {}
|
||||
};
|
||||
|
||||
class Fixture {
|
||||
private:
|
||||
struct Runner : public apache::thrift::concurrency::Runnable {
|
||||
int port;
|
||||
boost::shared_ptr<event_base> userEventBase;
|
||||
boost::shared_ptr<TProcessor> processor;
|
||||
boost::shared_ptr<server::TNonblockingServer> server;
|
||||
|
||||
virtual void run() {
|
||||
// When binding to explicit port, allow retrying to workaround bind failures on ports in use
|
||||
int retryCount = port ? 10 : 0;
|
||||
startServer(retryCount);
|
||||
}
|
||||
|
||||
private:
|
||||
void startServer(int retry_count) {
|
||||
try {
|
||||
server.reset(new server::TNonblockingServer(processor, port));
|
||||
if (userEventBase) {
|
||||
server->registerEvents(userEventBase.get());
|
||||
}
|
||||
server->serve();
|
||||
} catch (const transport::TTransportException&) {
|
||||
if (retry_count > 0) {
|
||||
++port;
|
||||
startServer(retry_count - 1);
|
||||
} else {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct EventDeleter {
|
||||
void operator()(event_base* p) { event_base_free(p); }
|
||||
};
|
||||
|
||||
protected:
|
||||
Fixture() : processor(new test::ParentServiceProcessor(boost::make_shared<Handler>())) {}
|
||||
|
||||
~Fixture() {
|
||||
if (server) {
|
||||
server->stop();
|
||||
}
|
||||
if (thread) {
|
||||
thread->join();
|
||||
}
|
||||
}
|
||||
|
||||
void setEventBase(event_base* user_event_base) {
|
||||
userEventBase_.reset(user_event_base, EventDeleter());
|
||||
}
|
||||
|
||||
int startServer(int port) {
|
||||
boost::shared_ptr<Runner> runner(new Runner);
|
||||
runner->port = port;
|
||||
runner->processor = processor;
|
||||
runner->userEventBase = userEventBase_;
|
||||
|
||||
boost::scoped_ptr<apache::thrift::concurrency::ThreadFactory> threadFactory(
|
||||
new apache::thrift::concurrency::PlatformThreadFactory(
|
||||
#if !USE_BOOST_THREAD && !USE_STD_THREAD
|
||||
concurrency::PlatformThreadFactory::OTHER, concurrency::PlatformThreadFactory::NORMAL,
|
||||
1,
|
||||
#endif
|
||||
false));
|
||||
thread = threadFactory->newThread(runner);
|
||||
thread->start();
|
||||
// wait 100 ms for the server to begin listening
|
||||
THRIFT_SLEEP_USEC(100000);
|
||||
server = runner->server;
|
||||
return runner->port;
|
||||
}
|
||||
|
||||
bool canCommunicate(int serverPort) {
|
||||
boost::shared_ptr<transport::TSocket> socket(new transport::TSocket("localhost", serverPort));
|
||||
socket->open();
|
||||
test::ParentServiceClient client(boost::make_shared<protocol::TBinaryProtocol>(
|
||||
boost::make_shared<transport::TFramedTransport>(socket)));
|
||||
client.addString("foo");
|
||||
std::vector<std::string> strings;
|
||||
client.getStrings(strings);
|
||||
return strings.size() == 1 && !(strings[0].compare("foo"));
|
||||
}
|
||||
|
||||
private:
|
||||
boost::shared_ptr<event_base> userEventBase_;
|
||||
boost::shared_ptr<test::ParentServiceProcessor> processor;
|
||||
protected:
|
||||
boost::shared_ptr<server::TNonblockingServer> server;
|
||||
private:
|
||||
boost::shared_ptr<apache::thrift::concurrency::Thread> thread;
|
||||
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(TNonblockingServerTest)
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(get_specified_port, Fixture) {
|
||||
int specified_port = startServer(12345);
|
||||
BOOST_REQUIRE_GE(specified_port, 12345);
|
||||
BOOST_REQUIRE_EQUAL(server->getListenPort(), specified_port);
|
||||
BOOST_CHECK(canCommunicate(specified_port));
|
||||
|
||||
server->stop();
|
||||
BOOST_CHECK_EQUAL(server->getListenPort(), specified_port);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(get_assigned_port, Fixture) {
|
||||
int specified_port = startServer(0);
|
||||
BOOST_REQUIRE_EQUAL(specified_port, 0);
|
||||
int assigned_port = server->getListenPort();
|
||||
BOOST_REQUIRE_NE(assigned_port, 0);
|
||||
BOOST_CHECK(canCommunicate(assigned_port));
|
||||
|
||||
server->stop();
|
||||
BOOST_CHECK_EQUAL(server->getListenPort(), 0);
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(provide_event_base, Fixture) {
|
||||
event_base* eb = event_base_new();
|
||||
setEventBase(eb);
|
||||
startServer(0);
|
||||
|
||||
// assert that the server works
|
||||
BOOST_CHECK(canCommunicate(server->getListenPort()));
|
||||
#if LIBEVENT_VERSION_NUMBER > 0x02010400
|
||||
// also assert that the event_base is actually used when it's easy
|
||||
BOOST_CHECK_GT(event_base_get_num_events(eb, EVENT_BASE_COUNT_ADDED), 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
89
vendor/git.apache.org/thrift.git/lib/cpp/test/TPipeInterruptTest.cpp
generated
vendored
Normal file
89
vendor/git.apache.org/thrift.git/lib/cpp/test/TPipeInterruptTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <boost/test/test_tools.hpp>
|
||||
#include <boost/test/unit_test_suite.hpp>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/chrono/duration.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_duration.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <thrift/transport/TPipe.h>
|
||||
#include <thrift/transport/TPipeServer.h>
|
||||
|
||||
using apache::thrift::transport::TPipeServer;
|
||||
using apache::thrift::transport::TPipe;
|
||||
using apache::thrift::transport::TTransport;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(TPipeInterruptTest)
|
||||
|
||||
// TODO: duplicate the test cases in TSocketInterruptTest for pipes,
|
||||
// once pipes implement interruptChildren
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_interrupt_before_accept) {
|
||||
TPipeServer pipe1("TPipeInterruptTest");
|
||||
pipe1.listen();
|
||||
pipe1.interrupt();
|
||||
BOOST_CHECK_THROW(pipe1.accept(), TTransportException);
|
||||
}
|
||||
|
||||
static void acceptWorker(TPipeServer *pipe) {
|
||||
try
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
boost::shared_ptr<TTransport> temp = pipe->accept();
|
||||
}
|
||||
}
|
||||
catch (...) {/*just want to make sure nothing crashes*/ }
|
||||
}
|
||||
|
||||
static void interruptWorker(TPipeServer *pipe) {
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(10));
|
||||
pipe->interrupt();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(stress_pipe_accept_interruption) {
|
||||
int interruptIters = 10;
|
||||
|
||||
for (int i = 0; i < interruptIters; ++i)
|
||||
{
|
||||
TPipeServer pipeServer("TPipeInterruptTest");
|
||||
pipeServer.listen();
|
||||
boost::thread acceptThread(boost::bind(acceptWorker, &pipeServer));
|
||||
boost::thread interruptThread(boost::bind(interruptWorker, &pipeServer));
|
||||
try
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
TPipe client("TPipeInterruptTest");
|
||||
client.setConnTimeout(1);
|
||||
client.open();
|
||||
}
|
||||
} catch (...) { /*just testing for crashes*/ }
|
||||
interruptThread.join();
|
||||
acceptThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
#endif
|
51
vendor/git.apache.org/thrift.git/lib/cpp/test/TPipedTransportTest.cpp
generated
vendored
Normal file
51
vendor/git.apache.org/thrift.git/lib/cpp/test/TPipedTransportTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <thrift/Thrift.h>
|
||||
#include <thrift/transport/TTransportUtils.h>
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
|
||||
#define BOOST_TEST_MODULE TPipedTransportTest
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
using apache::thrift::transport::TTransportException;
|
||||
using apache::thrift::transport::TPipedTransport;
|
||||
using apache::thrift::transport::TMemoryBuffer;
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_read_write) {
|
||||
boost::shared_ptr<TMemoryBuffer> underlying(new TMemoryBuffer);
|
||||
boost::shared_ptr<TMemoryBuffer> pipe(new TMemoryBuffer);
|
||||
boost::shared_ptr<TPipedTransport> trans(new TPipedTransport(underlying, pipe));
|
||||
|
||||
uint8_t buffer[4];
|
||||
|
||||
underlying->write((uint8_t*)"abcd", 4);
|
||||
trans->readAll(buffer, 2);
|
||||
BOOST_CHECK(std::string((char*)buffer, 2) == "ab");
|
||||
trans->readEnd();
|
||||
BOOST_CHECK(pipe->getBufferAsString() == "ab");
|
||||
pipe->resetBuffer();
|
||||
underlying->write((uint8_t*)"ef", 2);
|
||||
trans->readAll(buffer, 2);
|
||||
BOOST_CHECK(std::string((char*)buffer, 2) == "cd");
|
||||
trans->readAll(buffer, 2);
|
||||
BOOST_CHECK(std::string((char*)buffer, 2) == "ef");
|
||||
trans->readEnd();
|
||||
BOOST_CHECK(pipe->getBufferAsString() == "cdef");
|
||||
}
|
280
vendor/git.apache.org/thrift.git/lib/cpp/test/TSSLSocketInterruptTest.cpp
generated
vendored
Normal file
280
vendor/git.apache.org/thrift.git/lib/cpp/test/TSSLSocketInterruptTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <boost/test/auto_unit_test.hpp>
|
||||
#include <boost/test/unit_test_suite.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/chrono/duration.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_duration.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <thrift/transport/TSSLSocket.h>
|
||||
#include <thrift/transport/TSSLServerSocket.h>
|
||||
#ifdef __linux__
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
using apache::thrift::transport::TSSLServerSocket;
|
||||
using apache::thrift::transport::TSSLSocket;
|
||||
using apache::thrift::transport::TTransport;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
using apache::thrift::transport::TSSLSocketFactory;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(TSSLSocketInterruptTest)
|
||||
|
||||
boost::filesystem::path keyDir;
|
||||
boost::filesystem::path certFile(const std::string& filename)
|
||||
{
|
||||
return keyDir / filename;
|
||||
}
|
||||
boost::mutex gMutex;
|
||||
|
||||
struct GlobalFixtureSSL
|
||||
{
|
||||
GlobalFixtureSSL()
|
||||
{
|
||||
using namespace boost::unit_test::framework;
|
||||
for (int i = 0; i < master_test_suite().argc; ++i)
|
||||
{
|
||||
BOOST_TEST_MESSAGE(boost::format("argv[%1%] = \"%2%\"") % i % master_test_suite().argv[i]);
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
// OpenSSL calls send() without MSG_NOSIGPIPE so writing to a socket that has
|
||||
// disconnected can cause a SIGPIPE signal...
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
TSSLSocketFactory::setManualOpenSSLInitialization(true);
|
||||
apache::thrift::transport::initializeOpenSSL();
|
||||
|
||||
keyDir = boost::filesystem::current_path().parent_path().parent_path().parent_path() / "test" / "keys";
|
||||
if (!boost::filesystem::exists(certFile("server.crt")))
|
||||
{
|
||||
keyDir = boost::filesystem::path(master_test_suite().argv[master_test_suite().argc - 1]);
|
||||
if (!boost::filesystem::exists(certFile("server.crt")))
|
||||
{
|
||||
throw std::invalid_argument("The last argument to this test must be the directory containing the test certificate(s).");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~GlobalFixtureSSL()
|
||||
{
|
||||
apache::thrift::transport::cleanupOpenSSL();
|
||||
#ifdef __linux__
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#if (BOOST_VERSION >= 105900)
|
||||
BOOST_GLOBAL_FIXTURE(GlobalFixtureSSL);
|
||||
#else
|
||||
BOOST_GLOBAL_FIXTURE(GlobalFixtureSSL)
|
||||
#endif
|
||||
|
||||
void readerWorker(boost::shared_ptr<TTransport> tt, uint32_t expectedResult) {
|
||||
uint8_t buf[4];
|
||||
try {
|
||||
tt->read(buf, 1);
|
||||
BOOST_CHECK_EQUAL(expectedResult, tt->read(buf, 4));
|
||||
} catch (const TTransportException& tx) {
|
||||
BOOST_CHECK_EQUAL(TTransportException::TIMED_OUT, tx.getType());
|
||||
}
|
||||
}
|
||||
|
||||
void readerWorkerMustThrow(boost::shared_ptr<TTransport> tt) {
|
||||
try {
|
||||
uint8_t buf[400];
|
||||
tt->read(buf, 1);
|
||||
tt->read(buf, 400);
|
||||
BOOST_ERROR("should not have gotten here");
|
||||
} catch (const TTransportException& tx) {
|
||||
BOOST_CHECK_EQUAL(TTransportException::INTERRUPTED, tx.getType());
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<TSSLSocketFactory> createServerSocketFactory() {
|
||||
boost::shared_ptr<TSSLSocketFactory> pServerSocketFactory;
|
||||
|
||||
pServerSocketFactory.reset(new TSSLSocketFactory());
|
||||
pServerSocketFactory->ciphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
|
||||
pServerSocketFactory->loadCertificate(certFile("server.crt").string().c_str());
|
||||
pServerSocketFactory->loadPrivateKey(certFile("server.key").string().c_str());
|
||||
pServerSocketFactory->server(true);
|
||||
return pServerSocketFactory;
|
||||
}
|
||||
|
||||
boost::shared_ptr<TSSLSocketFactory> createClientSocketFactory() {
|
||||
boost::shared_ptr<TSSLSocketFactory> pClientSocketFactory;
|
||||
|
||||
pClientSocketFactory.reset(new TSSLSocketFactory());
|
||||
pClientSocketFactory->authenticate(true);
|
||||
pClientSocketFactory->loadCertificate(certFile("client.crt").string().c_str());
|
||||
pClientSocketFactory->loadPrivateKey(certFile("client.key").string().c_str());
|
||||
pClientSocketFactory->loadTrustedCertificates(certFile("CA.pem").string().c_str());
|
||||
return pClientSocketFactory;
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_ssl_interruptable_child_read_while_handshaking) {
|
||||
boost::shared_ptr<TSSLSocketFactory> pServerSocketFactory = createServerSocketFactory();
|
||||
TSSLServerSocket sock1("localhost", 0, pServerSocketFactory);
|
||||
sock1.listen();
|
||||
int port = sock1.getPort();
|
||||
boost::shared_ptr<TSSLSocketFactory> pClientSocketFactory = createClientSocketFactory();
|
||||
boost::shared_ptr<TSSLSocket> clientSock = pClientSocketFactory->createSocket("localhost", port);
|
||||
clientSock->open();
|
||||
boost::shared_ptr<TTransport> accepted = sock1.accept();
|
||||
boost::thread readThread(boost::bind(readerWorkerMustThrow, accepted));
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
||||
// readThread is practically guaranteed to be blocking now
|
||||
sock1.interruptChildren();
|
||||
BOOST_CHECK_MESSAGE(readThread.try_join_for(boost::chrono::milliseconds(20)),
|
||||
"server socket interruptChildren did not interrupt child read");
|
||||
clientSock->close();
|
||||
accepted->close();
|
||||
sock1.close();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_ssl_interruptable_child_read) {
|
||||
boost::shared_ptr<TSSLSocketFactory> pServerSocketFactory = createServerSocketFactory();
|
||||
TSSLServerSocket sock1("localhost", 0, pServerSocketFactory);
|
||||
sock1.listen();
|
||||
int port = sock1.getPort();
|
||||
boost::shared_ptr<TSSLSocketFactory> pClientSocketFactory = createClientSocketFactory();
|
||||
boost::shared_ptr<TSSLSocket> clientSock = pClientSocketFactory->createSocket("localhost", port);
|
||||
clientSock->open();
|
||||
boost::shared_ptr<TTransport> accepted = sock1.accept();
|
||||
boost::thread readThread(boost::bind(readerWorkerMustThrow, accepted));
|
||||
clientSock->write((const uint8_t*)"0", 1);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
||||
// readThread is practically guaranteed to be blocking now
|
||||
sock1.interruptChildren();
|
||||
BOOST_CHECK_MESSAGE(readThread.try_join_for(boost::chrono::milliseconds(20)),
|
||||
"server socket interruptChildren did not interrupt child read");
|
||||
accepted->close();
|
||||
clientSock->close();
|
||||
sock1.close();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_ssl_non_interruptable_child_read) {
|
||||
boost::shared_ptr<TSSLSocketFactory> pServerSocketFactory = createServerSocketFactory();
|
||||
TSSLServerSocket sock1("localhost", 0, pServerSocketFactory);
|
||||
sock1.setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior
|
||||
sock1.listen();
|
||||
int port = sock1.getPort();
|
||||
boost::shared_ptr<TSSLSocketFactory> pClientSocketFactory = createClientSocketFactory();
|
||||
boost::shared_ptr<TSSLSocket> clientSock = pClientSocketFactory->createSocket("localhost", port);
|
||||
clientSock->open();
|
||||
boost::shared_ptr<TTransport> accepted = sock1.accept();
|
||||
boost::static_pointer_cast<TSSLSocket>(accepted)->setRecvTimeout(1000);
|
||||
boost::thread readThread(boost::bind(readerWorker, accepted, 0));
|
||||
clientSock->write((const uint8_t*)"0", 1);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
||||
// readThread is practically guaranteed to be blocking here
|
||||
sock1.interruptChildren();
|
||||
BOOST_CHECK_MESSAGE(!readThread.try_join_for(boost::chrono::milliseconds(200)),
|
||||
"server socket interruptChildren interrupted child read");
|
||||
|
||||
// wait for receive timeout to kick in
|
||||
readThread.join();
|
||||
accepted->close();
|
||||
clientSock->close();
|
||||
sock1.close();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_ssl_cannot_change_after_listen) {
|
||||
boost::shared_ptr<TSSLSocketFactory> pServerSocketFactory = createServerSocketFactory();
|
||||
TSSLServerSocket sock1("localhost", 0, pServerSocketFactory);
|
||||
sock1.listen();
|
||||
BOOST_CHECK_THROW(sock1.setInterruptableChildren(false), std::logic_error);
|
||||
sock1.close();
|
||||
}
|
||||
|
||||
void peekerWorker(boost::shared_ptr<TTransport> tt, bool expectedResult) {
|
||||
uint8_t buf[400];
|
||||
try {
|
||||
tt->read(buf, 1);
|
||||
tt->peek();
|
||||
} catch (const TTransportException& tx) {
|
||||
BOOST_CHECK_EQUAL(TTransportException::TIMED_OUT, tx.getType());
|
||||
}
|
||||
}
|
||||
|
||||
void peekerWorkerInterrupt(boost::shared_ptr<TTransport> tt) {
|
||||
uint8_t buf[400];
|
||||
try {
|
||||
tt->read(buf, 1);
|
||||
tt->peek();
|
||||
} catch (const TTransportException& tx) {
|
||||
BOOST_CHECK_EQUAL(TTransportException::INTERRUPTED, tx.getType());
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_ssl_interruptable_child_peek) {
|
||||
boost::shared_ptr<TSSLSocketFactory> pServerSocketFactory = createServerSocketFactory();
|
||||
TSSLServerSocket sock1("localhost", 0, pServerSocketFactory);
|
||||
sock1.listen();
|
||||
int port = sock1.getPort();
|
||||
boost::shared_ptr<TSSLSocketFactory> pClientSocketFactory = createClientSocketFactory();
|
||||
boost::shared_ptr<TSSLSocket> clientSock = pClientSocketFactory->createSocket("localhost", port);
|
||||
clientSock->open();
|
||||
boost::shared_ptr<TTransport> accepted = sock1.accept();
|
||||
boost::thread peekThread(boost::bind(peekerWorkerInterrupt, accepted));
|
||||
clientSock->write((const uint8_t*)"0", 1);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
||||
// peekThread is practically guaranteed to be blocking now
|
||||
sock1.interruptChildren();
|
||||
BOOST_CHECK_MESSAGE(peekThread.try_join_for(boost::chrono::milliseconds(200)),
|
||||
"server socket interruptChildren did not interrupt child peek");
|
||||
accepted->close();
|
||||
clientSock->close();
|
||||
sock1.close();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_ssl_non_interruptable_child_peek) {
|
||||
boost::shared_ptr<TSSLSocketFactory> pServerSocketFactory = createServerSocketFactory();
|
||||
TSSLServerSocket sock1("localhost", 0, pServerSocketFactory);
|
||||
sock1.setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior
|
||||
sock1.listen();
|
||||
int port = sock1.getPort();
|
||||
boost::shared_ptr<TSSLSocketFactory> pClientSocketFactory = createClientSocketFactory();
|
||||
boost::shared_ptr<TSSLSocket> clientSock = pClientSocketFactory->createSocket("localhost", port);
|
||||
clientSock->open();
|
||||
boost::shared_ptr<TTransport> accepted = sock1.accept();
|
||||
boost::static_pointer_cast<TSSLSocket>(accepted)->setRecvTimeout(1000);
|
||||
boost::thread peekThread(boost::bind(peekerWorker, accepted, false));
|
||||
clientSock->write((const uint8_t*)"0", 1);
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
||||
// peekThread is practically guaranteed to be blocking now
|
||||
sock1.interruptChildren();
|
||||
BOOST_CHECK_MESSAGE(!peekThread.try_join_for(boost::chrono::milliseconds(200)),
|
||||
"server socket interruptChildren interrupted child peek");
|
||||
|
||||
// wait for the receive timeout to kick in
|
||||
peekThread.join();
|
||||
accepted->close();
|
||||
clientSock->close();
|
||||
sock1.close();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
534
vendor/git.apache.org/thrift.git/lib/cpp/test/TServerIntegrationTest.cpp
generated
vendored
Normal file
534
vendor/git.apache.org/thrift.git/lib/cpp/test/TServerIntegrationTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,534 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE TServerIntegrationTest
|
||||
#include <boost/test/auto_unit_test.hpp>
|
||||
#include <boost/atomic.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/date_time/posix_time/ptime.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/format.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <thrift/server/TSimpleServer.h>
|
||||
#include <thrift/server/TThreadPoolServer.h>
|
||||
#include <thrift/server/TThreadedServer.h>
|
||||
#include <thrift/protocol/TBinaryProtocol.h>
|
||||
#include <thrift/transport/TServerSocket.h>
|
||||
#include <thrift/transport/TSocket.h>
|
||||
#include <thrift/transport/TTransport.h>
|
||||
#include "gen-cpp/ParentService.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using apache::thrift::concurrency::Guard;
|
||||
using apache::thrift::concurrency::Monitor;
|
||||
using apache::thrift::concurrency::Mutex;
|
||||
using apache::thrift::concurrency::Synchronized;
|
||||
using apache::thrift::protocol::TBinaryProtocol;
|
||||
using apache::thrift::protocol::TBinaryProtocolFactory;
|
||||
using apache::thrift::protocol::TProtocol;
|
||||
using apache::thrift::protocol::TProtocolFactory;
|
||||
using apache::thrift::transport::TServerSocket;
|
||||
using apache::thrift::transport::TServerTransport;
|
||||
using apache::thrift::transport::TSocket;
|
||||
using apache::thrift::transport::TTransport;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
using apache::thrift::transport::TTransportFactory;
|
||||
using apache::thrift::server::TServer;
|
||||
using apache::thrift::server::TServerEventHandler;
|
||||
using apache::thrift::server::TSimpleServer;
|
||||
using apache::thrift::server::TThreadPoolServer;
|
||||
using apache::thrift::server::TThreadedServer;
|
||||
using apache::thrift::test::ParentServiceClient;
|
||||
using apache::thrift::test::ParentServiceIf;
|
||||
using apache::thrift::test::ParentServiceIfFactory;
|
||||
using apache::thrift::test::ParentServiceIfSingletonFactory;
|
||||
using apache::thrift::test::ParentServiceProcessor;
|
||||
using apache::thrift::test::ParentServiceProcessorFactory;
|
||||
using apache::thrift::TProcessor;
|
||||
using apache::thrift::TProcessorFactory;
|
||||
using boost::posix_time::milliseconds;
|
||||
|
||||
/**
|
||||
* preServe runs after listen() is successful, when we can connect
|
||||
*/
|
||||
class TServerReadyEventHandler : public TServerEventHandler, public Monitor {
|
||||
public:
|
||||
TServerReadyEventHandler() : isListening_(false), accepted_(0) {}
|
||||
virtual ~TServerReadyEventHandler() {}
|
||||
virtual void preServe() {
|
||||
Synchronized sync(*this);
|
||||
isListening_ = true;
|
||||
notify();
|
||||
}
|
||||
virtual void* createContext(boost::shared_ptr<TProtocol> input,
|
||||
boost::shared_ptr<TProtocol> output) {
|
||||
Synchronized sync(*this);
|
||||
++accepted_;
|
||||
notify();
|
||||
|
||||
(void)input;
|
||||
(void)output;
|
||||
return NULL;
|
||||
}
|
||||
bool isListening() const { return isListening_; }
|
||||
uint64_t acceptedCount() const { return accepted_; }
|
||||
|
||||
private:
|
||||
bool isListening_;
|
||||
uint64_t accepted_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reusing another generated test, just something to serve up
|
||||
*/
|
||||
class ParentHandler : public ParentServiceIf {
|
||||
public:
|
||||
ParentHandler() : generation_(0) {}
|
||||
|
||||
int32_t incrementGeneration() {
|
||||
Guard g(mutex_);
|
||||
return ++generation_;
|
||||
}
|
||||
|
||||
int32_t getGeneration() {
|
||||
Guard g(mutex_);
|
||||
return generation_;
|
||||
}
|
||||
|
||||
void addString(const std::string& s) {
|
||||
Guard g(mutex_);
|
||||
strings_.push_back(s);
|
||||
}
|
||||
|
||||
void getStrings(std::vector<std::string>& _return) {
|
||||
Guard g(mutex_);
|
||||
_return = strings_;
|
||||
}
|
||||
|
||||
void getDataWait(std::string& _return, const int32_t length) {
|
||||
THRIFT_UNUSED_VARIABLE(_return);
|
||||
THRIFT_UNUSED_VARIABLE(length);
|
||||
}
|
||||
|
||||
void onewayWait() {}
|
||||
|
||||
void exceptionWait(const std::string& message) { THRIFT_UNUSED_VARIABLE(message); }
|
||||
|
||||
void unexpectedExceptionWait(const std::string& message) { THRIFT_UNUSED_VARIABLE(message); }
|
||||
|
||||
protected:
|
||||
Mutex mutex_;
|
||||
int32_t generation_;
|
||||
std::vector<std::string> strings_;
|
||||
};
|
||||
|
||||
void autoSocketCloser(TSocket* pSock) {
|
||||
pSock->close();
|
||||
delete pSock;
|
||||
}
|
||||
|
||||
template <class TServerType>
|
||||
class TServerIntegrationTestFixture {
|
||||
public:
|
||||
TServerIntegrationTestFixture(const boost::shared_ptr<TProcessorFactory>& _processorFactory)
|
||||
: pServer(new TServerType(_processorFactory,
|
||||
boost::shared_ptr<TServerTransport>(
|
||||
new TServerSocket("localhost", 0)),
|
||||
boost::shared_ptr<TTransportFactory>(new TTransportFactory),
|
||||
boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory))),
|
||||
pEventHandler(boost::shared_ptr<TServerReadyEventHandler>(new TServerReadyEventHandler)),
|
||||
bStressDone(false),
|
||||
bStressConnectionCount(0),
|
||||
bStressRequestCount(0) {
|
||||
pServer->setServerEventHandler(pEventHandler);
|
||||
}
|
||||
|
||||
TServerIntegrationTestFixture(const boost::shared_ptr<TProcessor>& _processor)
|
||||
: pServer(
|
||||
new TServerType(_processor,
|
||||
boost::shared_ptr<TServerTransport>(new TServerSocket("localhost", 0)),
|
||||
boost::shared_ptr<TTransportFactory>(new TTransportFactory),
|
||||
boost::shared_ptr<TProtocolFactory>(new TBinaryProtocolFactory))),
|
||||
pEventHandler(boost::shared_ptr<TServerReadyEventHandler>(new TServerReadyEventHandler)),
|
||||
bStressDone(false),
|
||||
bStressConnectionCount(0),
|
||||
bStressRequestCount(0) {
|
||||
pServer->setServerEventHandler(pEventHandler);
|
||||
}
|
||||
|
||||
void startServer() {
|
||||
pServerThread.reset(new boost::thread(boost::bind(&TServerType::serve, pServer.get())));
|
||||
|
||||
// block until listen() completes so clients will be able to connect
|
||||
Synchronized sync(*(pEventHandler.get()));
|
||||
while (!pEventHandler->isListening()) {
|
||||
pEventHandler->wait();
|
||||
}
|
||||
|
||||
BOOST_TEST_MESSAGE(" server is listening");
|
||||
}
|
||||
|
||||
void blockUntilAccepted(uint64_t numAccepted) {
|
||||
Synchronized sync(*(pEventHandler.get()));
|
||||
while (pEventHandler->acceptedCount() < numAccepted) {
|
||||
pEventHandler->wait();
|
||||
}
|
||||
|
||||
BOOST_TEST_MESSAGE(boost::format(" server has accepted %1%") % numAccepted);
|
||||
}
|
||||
|
||||
void stopServer() {
|
||||
if (pServerThread) {
|
||||
pServer->stop();
|
||||
BOOST_TEST_MESSAGE(" server stop completed");
|
||||
|
||||
pServerThread->join();
|
||||
BOOST_TEST_MESSAGE(" server thread joined");
|
||||
pServerThread.reset();
|
||||
}
|
||||
}
|
||||
|
||||
~TServerIntegrationTestFixture() { stopServer(); }
|
||||
|
||||
/**
|
||||
* Performs a baseline test where some clients are opened and issue a single operation
|
||||
* and then disconnect at different intervals.
|
||||
* \param[in] numToMake the number of concurrent clients
|
||||
* \param[in] expectedHWM the high water mark we expect of concurrency
|
||||
* \param[in] purpose a description of the test for logging purposes
|
||||
*/
|
||||
void baseline(int64_t numToMake, int64_t expectedHWM, const std::string& purpose) {
|
||||
BOOST_TEST_MESSAGE(boost::format("Testing %1%: %2% with %3% clients, expect %4% HWM")
|
||||
% typeid(TServerType).name() % purpose % numToMake % expectedHWM);
|
||||
|
||||
startServer();
|
||||
|
||||
std::vector<boost::shared_ptr<TSocket> > holdSockets;
|
||||
std::vector<boost::shared_ptr<boost::thread> > holdThreads;
|
||||
|
||||
for (int64_t i = 0; i < numToMake; ++i) {
|
||||
boost::shared_ptr<TSocket> pClientSock(new TSocket("localhost", getServerPort()),
|
||||
autoSocketCloser);
|
||||
holdSockets.push_back(pClientSock);
|
||||
boost::shared_ptr<TProtocol> pClientProtocol(new TBinaryProtocol(pClientSock));
|
||||
ParentServiceClient client(pClientProtocol);
|
||||
pClientSock->open();
|
||||
client.incrementGeneration();
|
||||
holdThreads.push_back(boost::shared_ptr<boost::thread>(
|
||||
new boost::thread(boost::bind(&TServerIntegrationTestFixture::delayClose,
|
||||
this,
|
||||
pClientSock,
|
||||
milliseconds(10 * numToMake)))));
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL(expectedHWM, pServer->getConcurrentClientCountHWM());
|
||||
|
||||
BOOST_FOREACH (boost::shared_ptr<boost::thread> pThread, holdThreads) { pThread->join(); }
|
||||
holdThreads.clear();
|
||||
holdSockets.clear();
|
||||
|
||||
stopServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method used to close a connection after a delay.
|
||||
* \param[in] toClose the connection to close
|
||||
* \param[in] after the delay to impose
|
||||
*/
|
||||
void delayClose(boost::shared_ptr<TTransport> toClose, boost::posix_time::time_duration after) {
|
||||
boost::this_thread::sleep(after);
|
||||
toClose->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* \returns the server port number
|
||||
*/
|
||||
int getServerPort() {
|
||||
TServerSocket* pSock = dynamic_cast<TServerSocket*>(pServer->getServerTransport().get());
|
||||
return pSock->getPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a stress test by spawning threads that connect, do a number of operations
|
||||
* and disconnect, then a random delay, then do it over again. This is done for a fixed
|
||||
* period of time to test for concurrency correctness.
|
||||
* \param[in] numToMake the number of concurrent clients
|
||||
*/
|
||||
void stress(int64_t numToMake, const boost::posix_time::time_duration& duration) {
|
||||
BOOST_TEST_MESSAGE(boost::format("Stress testing %1% with %2% clients for %3% seconds")
|
||||
% typeid(TServerType).name() % numToMake % duration.total_seconds());
|
||||
|
||||
startServer();
|
||||
|
||||
std::vector<boost::shared_ptr<boost::thread> > holdThreads;
|
||||
for (int64_t i = 0; i < numToMake; ++i) {
|
||||
holdThreads.push_back(boost::shared_ptr<boost::thread>(
|
||||
new boost::thread(boost::bind(&TServerIntegrationTestFixture::stressor, this))));
|
||||
}
|
||||
|
||||
boost::this_thread::sleep(duration);
|
||||
bStressDone = true;
|
||||
|
||||
BOOST_TEST_MESSAGE(boost::format(" serviced %1% connections (HWM %2%) totaling %3% requests")
|
||||
% bStressConnectionCount % pServer->getConcurrentClientCountHWM() % bStressRequestCount);
|
||||
|
||||
BOOST_FOREACH (boost::shared_ptr<boost::thread> pThread, holdThreads) { pThread->join(); }
|
||||
holdThreads.clear();
|
||||
|
||||
BOOST_CHECK(bStressRequestCount > 0);
|
||||
|
||||
stopServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to stress the system
|
||||
*/
|
||||
void stressor() {
|
||||
while (!bStressDone) {
|
||||
boost::shared_ptr<TSocket> pSocket(new TSocket("localhost", getServerPort()), autoSocketCloser);
|
||||
boost::shared_ptr<TProtocol> pProtocol(new TBinaryProtocol(pSocket));
|
||||
ParentServiceClient client(pProtocol);
|
||||
pSocket->open();
|
||||
bStressConnectionCount.fetch_add(1, boost::memory_order_relaxed);
|
||||
for (int i = 0; i < rand() % 1000; ++i) {
|
||||
client.incrementGeneration();
|
||||
bStressRequestCount.fetch_add(1, boost::memory_order_relaxed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<TServerType> pServer;
|
||||
boost::shared_ptr<TServerReadyEventHandler> pEventHandler;
|
||||
boost::shared_ptr<boost::thread> pServerThread;
|
||||
bool bStressDone;
|
||||
boost::atomic_int64_t bStressConnectionCount;
|
||||
boost::atomic_int64_t bStressRequestCount;
|
||||
};
|
||||
|
||||
template <class TServerType>
|
||||
class TServerIntegrationProcessorFactoryTestFixture
|
||||
: public TServerIntegrationTestFixture<TServerType> {
|
||||
public:
|
||||
TServerIntegrationProcessorFactoryTestFixture()
|
||||
: TServerIntegrationTestFixture<TServerType>(boost::make_shared<ParentServiceProcessorFactory>(
|
||||
boost::make_shared<ParentServiceIfSingletonFactory>(
|
||||
boost::make_shared<ParentHandler>()))) {}
|
||||
};
|
||||
|
||||
template <class TServerType>
|
||||
class TServerIntegrationProcessorTestFixture : public TServerIntegrationTestFixture<TServerType> {
|
||||
public:
|
||||
TServerIntegrationProcessorTestFixture()
|
||||
: TServerIntegrationTestFixture<TServerType>(
|
||||
boost::make_shared<ParentServiceProcessor>(boost::make_shared<ParentHandler>())) {}
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(constructors)
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_simple_factory,
|
||||
TServerIntegrationProcessorFactoryTestFixture<TSimpleServer>) {
|
||||
baseline(3, 1, "factory");
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_simple, TServerIntegrationProcessorTestFixture<TSimpleServer>) {
|
||||
baseline(3, 1, "processor");
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_threaded_factory,
|
||||
TServerIntegrationProcessorFactoryTestFixture<TThreadedServer>) {
|
||||
baseline(10, 10, "factory");
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_threaded, TServerIntegrationProcessorTestFixture<TThreadedServer>) {
|
||||
baseline(10, 10, "processor");
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_threaded_bound,
|
||||
TServerIntegrationProcessorTestFixture<TThreadedServer>) {
|
||||
pServer->setConcurrentClientLimit(4);
|
||||
baseline(10, 4, "limit by server framework");
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_threaded_stress,
|
||||
TServerIntegrationProcessorFactoryTestFixture<TThreadedServer>) {
|
||||
stress(10, boost::posix_time::seconds(3));
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_threadpool_factory,
|
||||
TServerIntegrationProcessorFactoryTestFixture<TThreadPoolServer>) {
|
||||
pServer->getThreadManager()->threadFactory(
|
||||
boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
|
||||
new apache::thrift::concurrency::PlatformThreadFactory));
|
||||
pServer->getThreadManager()->start();
|
||||
|
||||
// thread factory has 4 threads as a default
|
||||
// thread factory however is a bad way to limit concurrent clients
|
||||
// as accept() will be called to grab a 5th client socket, in this case
|
||||
// and then the thread factory will block adding the thread to manage
|
||||
// that client.
|
||||
baseline(10, 5, "limit by thread manager");
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_threadpool,
|
||||
TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
|
||||
pServer->getThreadManager()->threadFactory(
|
||||
boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
|
||||
new apache::thrift::concurrency::PlatformThreadFactory));
|
||||
pServer->getThreadManager()->start();
|
||||
|
||||
// thread factory has 4 threads as a default
|
||||
// thread factory however is a bad way to limit concurrent clients
|
||||
// as accept() will be called to grab a 5th client socket, in this case
|
||||
// and then the thread factory will block adding the thread to manage
|
||||
// that client.
|
||||
baseline(10, 5, "limit by thread manager");
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_threadpool_bound,
|
||||
TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
|
||||
pServer->getThreadManager()->threadFactory(
|
||||
boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
|
||||
new apache::thrift::concurrency::PlatformThreadFactory));
|
||||
pServer->getThreadManager()->start();
|
||||
pServer->setConcurrentClientLimit(4);
|
||||
|
||||
baseline(10, 4, "server framework connection limit");
|
||||
}
|
||||
|
||||
BOOST_FIXTURE_TEST_CASE(test_threadpool_stress,
|
||||
TServerIntegrationProcessorTestFixture<TThreadPoolServer>) {
|
||||
pServer->getThreadManager()->threadFactory(
|
||||
boost::shared_ptr<apache::thrift::concurrency::ThreadFactory>(
|
||||
new apache::thrift::concurrency::PlatformThreadFactory));
|
||||
pServer->getThreadManager()->start();
|
||||
|
||||
stress(10, boost::posix_time::seconds(3));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
BOOST_FIXTURE_TEST_SUITE(TServerIntegrationTest,
|
||||
TServerIntegrationProcessorTestFixture<TThreadedServer>)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_stop_with_interruptable_clients_connected) {
|
||||
// This tests THRIFT-2441 new behavior: stopping the server disconnects clients
|
||||
BOOST_TEST_MESSAGE("Testing stop with interruptable clients");
|
||||
|
||||
startServer();
|
||||
|
||||
boost::shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
|
||||
autoSocketCloser);
|
||||
pClientSock1->open();
|
||||
|
||||
boost::shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
|
||||
autoSocketCloser);
|
||||
pClientSock2->open();
|
||||
|
||||
// Ensure they have been accepted
|
||||
blockUntilAccepted(2);
|
||||
|
||||
// The test fixture destructor will force the sockets to disconnect
|
||||
// Prior to THRIFT-2441, pServer->stop() would hang until clients disconnected
|
||||
stopServer();
|
||||
|
||||
// extra proof the server end disconnected the clients
|
||||
uint8_t buf[1];
|
||||
BOOST_CHECK_EQUAL(0, pClientSock1->read(&buf[0], 1)); // 0 = disconnected
|
||||
BOOST_CHECK_EQUAL(0, pClientSock2->read(&buf[0], 1)); // 0 = disconnected
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_stop_with_uninterruptable_clients_connected) {
|
||||
// This tests pre-THRIFT-2441 behavior: stopping the server blocks until clients
|
||||
// disconnect.
|
||||
BOOST_TEST_MESSAGE("Testing stop with uninterruptable clients");
|
||||
|
||||
boost::dynamic_pointer_cast<TServerSocket>(pServer->getServerTransport())
|
||||
->setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior
|
||||
|
||||
startServer();
|
||||
|
||||
boost::shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
|
||||
autoSocketCloser);
|
||||
pClientSock1->open();
|
||||
|
||||
boost::shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
|
||||
autoSocketCloser);
|
||||
pClientSock2->open();
|
||||
|
||||
// Ensure they have been accepted
|
||||
blockUntilAccepted(2);
|
||||
|
||||
boost::thread t1(boost::bind(&TServerIntegrationTestFixture::delayClose,
|
||||
this,
|
||||
pClientSock1,
|
||||
milliseconds(250)));
|
||||
boost::thread t2(boost::bind(&TServerIntegrationTestFixture::delayClose,
|
||||
this,
|
||||
pClientSock2,
|
||||
milliseconds(250)));
|
||||
|
||||
// Once the clients disconnect the server will stop
|
||||
stopServer();
|
||||
BOOST_CHECK(pServer->getConcurrentClientCountHWM() > 0);
|
||||
t1.join();
|
||||
t2.join();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_concurrent_client_limit) {
|
||||
startServer();
|
||||
BOOST_TEST_MESSAGE("Testing the concurrent client limit");
|
||||
|
||||
BOOST_CHECK_EQUAL(INT64_MAX, pServer->getConcurrentClientLimit());
|
||||
pServer->setConcurrentClientLimit(2);
|
||||
BOOST_CHECK_EQUAL(0, pServer->getConcurrentClientCount());
|
||||
BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientLimit());
|
||||
|
||||
boost::shared_ptr<TSocket> pClientSock1(new TSocket("localhost", getServerPort()),
|
||||
autoSocketCloser);
|
||||
pClientSock1->open();
|
||||
blockUntilAccepted(1);
|
||||
BOOST_CHECK_EQUAL(1, pServer->getConcurrentClientCount());
|
||||
|
||||
boost::shared_ptr<TSocket> pClientSock2(new TSocket("localhost", getServerPort()),
|
||||
autoSocketCloser);
|
||||
pClientSock2->open();
|
||||
blockUntilAccepted(2);
|
||||
BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount());
|
||||
|
||||
// a third client cannot connect until one of the other two closes
|
||||
boost::thread t2(boost::bind(&TServerIntegrationTestFixture::delayClose,
|
||||
this,
|
||||
pClientSock2,
|
||||
milliseconds(250)));
|
||||
boost::shared_ptr<TSocket> pClientSock3(new TSocket("localhost", getServerPort()),
|
||||
autoSocketCloser);
|
||||
pClientSock2->open();
|
||||
blockUntilAccepted(2);
|
||||
BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCount());
|
||||
BOOST_CHECK_EQUAL(2, pServer->getConcurrentClientCountHWM());
|
||||
|
||||
stopServer();
|
||||
BOOST_CHECK(pServer->getConcurrentClientCountHWM() > 0);
|
||||
t2.join();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
67
vendor/git.apache.org/thrift.git/lib/cpp/test/TServerSocketTest.cpp
generated
vendored
Normal file
67
vendor/git.apache.org/thrift.git/lib/cpp/test/TServerSocketTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <boost/test/auto_unit_test.hpp>
|
||||
#include <thrift/transport/TSocket.h>
|
||||
#include <thrift/transport/TServerSocket.h>
|
||||
#include "TTransportCheckThrow.h"
|
||||
#include <iostream>
|
||||
|
||||
using apache::thrift::transport::TServerSocket;
|
||||
using apache::thrift::transport::TSocket;
|
||||
using apache::thrift::transport::TTransport;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(TServerSocketTest)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_bind_to_address) {
|
||||
TServerSocket sock1("localhost", 0);
|
||||
sock1.listen();
|
||||
int port = sock1.getPort();
|
||||
TSocket clientSock("localhost", port);
|
||||
clientSock.open();
|
||||
boost::shared_ptr<TTransport> accepted = sock1.accept();
|
||||
accepted->close();
|
||||
sock1.close();
|
||||
|
||||
std::cout << "An error message from getaddrinfo on the console is expected:" << std::endl;
|
||||
TServerSocket sock2("257.258.259.260", 0);
|
||||
BOOST_CHECK_THROW(sock2.listen(), TTransportException);
|
||||
sock2.close();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_listen_valid_port) {
|
||||
TServerSocket sock1(-1);
|
||||
TTRANSPORT_CHECK_THROW(sock1.listen(), TTransportException::BAD_ARGS);
|
||||
|
||||
TServerSocket sock2(65536);
|
||||
TTRANSPORT_CHECK_THROW(sock2.listen(), TTransportException::BAD_ARGS);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_close_before_listen) {
|
||||
TServerSocket sock1("localhost", 0);
|
||||
sock1.close();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_get_port) {
|
||||
TServerSocket sock1("localHost", 888);
|
||||
BOOST_CHECK_EQUAL(888, sock1.getPort());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
56
vendor/git.apache.org/thrift.git/lib/cpp/test/TServerTransportTest.cpp
generated
vendored
Normal file
56
vendor/git.apache.org/thrift.git/lib/cpp/test/TServerTransportTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <boost/test/auto_unit_test.hpp>
|
||||
#include <thrift/transport/TSocket.h>
|
||||
#include <thrift/transport/TServerTransport.h>
|
||||
|
||||
using apache::thrift::transport::TServerTransport;
|
||||
using apache::thrift::transport::TTransport;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(TServerTransportTest)
|
||||
|
||||
class TestTTransport : public TTransport {};
|
||||
|
||||
class TestTServerTransport : public TServerTransport {
|
||||
public:
|
||||
TestTServerTransport() : valid_(true) {}
|
||||
void close() {}
|
||||
bool valid_;
|
||||
|
||||
protected:
|
||||
boost::shared_ptr<TTransport> acceptImpl() {
|
||||
return valid_ ? boost::shared_ptr<TestTTransport>(new TestTTransport)
|
||||
: boost::shared_ptr<TestTTransport>();
|
||||
}
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_positive_accept) {
|
||||
TestTServerTransport uut;
|
||||
BOOST_CHECK(uut.accept());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_negative_accept) {
|
||||
TestTServerTransport uut;
|
||||
uut.valid_ = false;
|
||||
BOOST_CHECK_THROW(uut.accept(), TTransportException);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
145
vendor/git.apache.org/thrift.git/lib/cpp/test/TSocketInterruptTest.cpp
generated
vendored
Normal file
145
vendor/git.apache.org/thrift.git/lib/cpp/test/TSocketInterruptTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE TSocketInterruptTest
|
||||
#include <boost/test/auto_unit_test.hpp>
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/chrono/duration.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time_duration.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <thrift/transport/TSocket.h>
|
||||
#include <thrift/transport/TServerSocket.h>
|
||||
|
||||
using apache::thrift::transport::TServerSocket;
|
||||
using apache::thrift::transport::TSocket;
|
||||
using apache::thrift::transport::TTransport;
|
||||
using apache::thrift::transport::TTransportException;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(TSocketInterruptTest)
|
||||
|
||||
void readerWorker(boost::shared_ptr<TTransport> tt, uint32_t expectedResult) {
|
||||
uint8_t buf[4];
|
||||
BOOST_CHECK_EQUAL(expectedResult, tt->read(buf, 4));
|
||||
}
|
||||
|
||||
void readerWorkerMustThrow(boost::shared_ptr<TTransport> tt) {
|
||||
try {
|
||||
uint8_t buf[4];
|
||||
tt->read(buf, 4);
|
||||
BOOST_ERROR("should not have gotten here");
|
||||
} catch (const TTransportException& tx) {
|
||||
BOOST_CHECK_EQUAL(TTransportException::INTERRUPTED, tx.getType());
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_interruptable_child_read) {
|
||||
TServerSocket sock1("localhost", 0);
|
||||
sock1.listen();
|
||||
int port = sock1.getPort();
|
||||
TSocket clientSock("localhost", port);
|
||||
clientSock.open();
|
||||
boost::shared_ptr<TTransport> accepted = sock1.accept();
|
||||
boost::thread readThread(boost::bind(readerWorkerMustThrow, accepted));
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
||||
// readThread is practically guaranteed to be blocking now
|
||||
sock1.interruptChildren();
|
||||
BOOST_CHECK_MESSAGE(readThread.try_join_for(boost::chrono::milliseconds(200)),
|
||||
"server socket interruptChildren did not interrupt child read");
|
||||
clientSock.close();
|
||||
accepted->close();
|
||||
sock1.close();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_non_interruptable_child_read) {
|
||||
TServerSocket sock1("localhost", 0);
|
||||
sock1.setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior
|
||||
sock1.listen();
|
||||
int port = sock1.getPort();
|
||||
TSocket clientSock("localhost", port);
|
||||
clientSock.open();
|
||||
boost::shared_ptr<TTransport> accepted = sock1.accept();
|
||||
boost::thread readThread(boost::bind(readerWorker, accepted, 0));
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
||||
// readThread is practically guaranteed to be blocking here
|
||||
sock1.interruptChildren();
|
||||
BOOST_CHECK_MESSAGE(!readThread.try_join_for(boost::chrono::milliseconds(200)),
|
||||
"server socket interruptChildren interrupted child read");
|
||||
|
||||
// only way to proceed is to have the client disconnect
|
||||
clientSock.close();
|
||||
readThread.join();
|
||||
accepted->close();
|
||||
sock1.close();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_cannot_change_after_listen) {
|
||||
TServerSocket sock1("localhost", 0);
|
||||
sock1.listen();
|
||||
BOOST_CHECK_THROW(sock1.setInterruptableChildren(false), std::logic_error);
|
||||
sock1.close();
|
||||
}
|
||||
|
||||
void peekerWorker(boost::shared_ptr<TTransport> tt, bool expectedResult) {
|
||||
BOOST_CHECK_EQUAL(expectedResult, tt->peek());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_interruptable_child_peek) {
|
||||
TServerSocket sock1("localhost", 0);
|
||||
sock1.listen();
|
||||
int port = sock1.getPort();
|
||||
TSocket clientSock("localhost", port);
|
||||
clientSock.open();
|
||||
boost::shared_ptr<TTransport> accepted = sock1.accept();
|
||||
// peek() will return false if child is interrupted
|
||||
boost::thread peekThread(boost::bind(peekerWorker, accepted, false));
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
||||
// peekThread is practically guaranteed to be blocking now
|
||||
sock1.interruptChildren();
|
||||
BOOST_CHECK_MESSAGE(peekThread.try_join_for(boost::chrono::milliseconds(200)),
|
||||
"server socket interruptChildren did not interrupt child peek");
|
||||
clientSock.close();
|
||||
accepted->close();
|
||||
sock1.close();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_non_interruptable_child_peek) {
|
||||
TServerSocket sock1("localhost", 0);
|
||||
sock1.setInterruptableChildren(false); // returns to pre-THRIFT-2441 behavior
|
||||
sock1.listen();
|
||||
int port = sock1.getPort();
|
||||
TSocket clientSock("localhost", port);
|
||||
clientSock.open();
|
||||
boost::shared_ptr<TTransport> accepted = sock1.accept();
|
||||
// peek() will return false when remote side is closed
|
||||
boost::thread peekThread(boost::bind(peekerWorker, accepted, false));
|
||||
boost::this_thread::sleep(boost::posix_time::milliseconds(50));
|
||||
// peekThread is practically guaranteed to be blocking now
|
||||
sock1.interruptChildren();
|
||||
BOOST_CHECK_MESSAGE(!peekThread.try_join_for(boost::chrono::milliseconds(200)),
|
||||
"server socket interruptChildren interrupted child peek");
|
||||
|
||||
// only way to proceed is to have the client disconnect
|
||||
clientSock.close();
|
||||
peekThread.join();
|
||||
accepted->close();
|
||||
sock1.close();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
44
vendor/git.apache.org/thrift.git/lib/cpp/test/TTransportCheckThrow.h
generated
vendored
Normal file
44
vendor/git.apache.org/thrift.git/lib/cpp/test/TTransportCheckThrow.h
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define TTRANSPORT_CHECK_THROW(_CALL, _TYPE) \
|
||||
{ \
|
||||
bool caught = false; \
|
||||
try { \
|
||||
(_CALL); \
|
||||
} catch (TTransportException & ex) { \
|
||||
BOOST_CHECK_EQUAL(ex.getType(), _TYPE); \
|
||||
caught = true; \
|
||||
} \
|
||||
BOOST_CHECK_MESSAGE(caught, "expected TTransportException but nothing was thrown"); \
|
||||
}
|
||||
|
||||
#define TTRANSPORT_REQUIRE_THROW(_CALL, _TYPE) \
|
||||
{ \
|
||||
bool caught = false; \
|
||||
try { \
|
||||
(_CALL); \
|
||||
} catch (TTransportException & ex) { \
|
||||
BOOST_REQUIRE_EQUAL(ex.getType(), _TYPE); \
|
||||
caught = true; \
|
||||
} \
|
||||
BOOST_REQUIRE_MESSAGE(caught, "expected TTransportException but nothing was thrown"); \
|
||||
}
|
33
vendor/git.apache.org/thrift.git/lib/cpp/test/ThriftTest_extras.cpp
generated
vendored
Normal file
33
vendor/git.apache.org/thrift.git/lib/cpp/test/ThriftTest_extras.cpp
generated
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// Extra functions required for ThriftTest_types to work
|
||||
|
||||
#include <thrift/protocol/TDebugProtocol.h>
|
||||
#include "gen-cpp/ThriftTest_types.h"
|
||||
|
||||
namespace thrift {
|
||||
namespace test {
|
||||
|
||||
bool Insanity::operator<(thrift::test::Insanity const& other) const {
|
||||
using apache::thrift::ThriftDebugString;
|
||||
return ThriftDebugString(*this) < ThriftDebugString(other);
|
||||
}
|
||||
}
|
||||
}
|
137
vendor/git.apache.org/thrift.git/lib/cpp/test/ToStringTest.cpp
generated
vendored
Normal file
137
vendor/git.apache.org/thrift.git/lib/cpp/test/ToStringTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <vector>
|
||||
#include <map>
|
||||
|
||||
#include <boost/test/auto_unit_test.hpp>
|
||||
|
||||
#include <thrift/TToString.h>
|
||||
|
||||
#include "gen-cpp/ThriftTest_types.h"
|
||||
#include "gen-cpp/OptionalRequiredTest_types.h"
|
||||
#include "gen-cpp/DebugProtoTest_types.h"
|
||||
|
||||
using apache::thrift::to_string;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(ToStringTest)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(base_types_to_string) {
|
||||
BOOST_CHECK_EQUAL(to_string(10), "10");
|
||||
BOOST_CHECK_EQUAL(to_string(true), "1");
|
||||
BOOST_CHECK_EQUAL(to_string('a'), "a");
|
||||
BOOST_CHECK_EQUAL(to_string(1.2), "1.2");
|
||||
BOOST_CHECK_EQUAL(to_string("abc"), "abc");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(empty_vector_to_string) {
|
||||
std::vector<int> l;
|
||||
BOOST_CHECK_EQUAL(to_string(l), "[]");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(single_item_vector_to_string) {
|
||||
std::vector<int> l;
|
||||
l.push_back(100);
|
||||
BOOST_CHECK_EQUAL(to_string(l), "[100]");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(multiple_item_vector_to_string) {
|
||||
std::vector<int> l;
|
||||
l.push_back(100);
|
||||
l.push_back(150);
|
||||
BOOST_CHECK_EQUAL(to_string(l), "[100, 150]");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(empty_map_to_string) {
|
||||
std::map<int, std::string> m;
|
||||
BOOST_CHECK_EQUAL(to_string(m), "{}");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(single_item_map_to_string) {
|
||||
std::map<int, std::string> m;
|
||||
m[12] = "abc";
|
||||
BOOST_CHECK_EQUAL(to_string(m), "{12: abc}");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(multi_item_map_to_string) {
|
||||
std::map<int, std::string> m;
|
||||
m[12] = "abc";
|
||||
m[31] = "xyz";
|
||||
BOOST_CHECK_EQUAL(to_string(m), "{12: abc, 31: xyz}");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(empty_set_to_string) {
|
||||
std::set<char> s;
|
||||
BOOST_CHECK_EQUAL(to_string(s), "{}");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(single_item_set_to_string) {
|
||||
std::set<char> s;
|
||||
s.insert('c');
|
||||
BOOST_CHECK_EQUAL(to_string(s), "{c}");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(multi_item_set_to_string) {
|
||||
std::set<char> s;
|
||||
s.insert('a');
|
||||
s.insert('z');
|
||||
BOOST_CHECK_EQUAL(to_string(s), "{a, z}");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(generated_empty_object_to_string) {
|
||||
thrift::test::EmptyStruct e;
|
||||
BOOST_CHECK_EQUAL(to_string(e), "EmptyStruct()");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(generated_single_basic_field_object_to_string) {
|
||||
thrift::test::StructA a;
|
||||
a.__set_s("abcd");
|
||||
BOOST_CHECK_EQUAL(to_string(a), "StructA(s=abcd)");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(generated_two_basic_fields_object_to_string) {
|
||||
thrift::test::Bonk a;
|
||||
a.__set_message("abcd");
|
||||
a.__set_type(1234);
|
||||
BOOST_CHECK_EQUAL(to_string(a), "Bonk(message=abcd, type=1234)");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(generated_optional_fields_object_to_string) {
|
||||
thrift::test::Tricky2 a;
|
||||
BOOST_CHECK_EQUAL(to_string(a), "Tricky2(im_optional=<null>)");
|
||||
a.__set_im_optional(123);
|
||||
BOOST_CHECK_EQUAL(to_string(a), "Tricky2(im_optional=123)");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(generated_nested_object_to_string) {
|
||||
thrift::test::OneField a;
|
||||
BOOST_CHECK_EQUAL(to_string(a), "OneField(field=EmptyStruct())");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(generated_nested_list_object_to_string) {
|
||||
thrift::test::ListBonks l;
|
||||
l.bonk.assign(2, thrift::test::Bonk());
|
||||
l.bonk[0].__set_message("a");
|
||||
l.bonk[1].__set_message("b");
|
||||
|
||||
BOOST_CHECK_EQUAL(to_string(l),
|
||||
"ListBonks(bonk=[Bonk(message=a, type=0), Bonk(message=b, type=0)])");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
1061
vendor/git.apache.org/thrift.git/lib/cpp/test/TransportTest.cpp
generated
vendored
Normal file
1061
vendor/git.apache.org/thrift.git/lib/cpp/test/TransportTest.cpp
generated
vendored
Normal file
File diff suppressed because it is too large
Load diff
28
vendor/git.apache.org/thrift.git/lib/cpp/test/TypedefTest.cpp
generated
vendored
Normal file
28
vendor/git.apache.org/thrift.git/lib/cpp/test/TypedefTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <boost/type_traits/is_same.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include "gen-cpp/TypedefTest_types.h"
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<int32_t, thrift::test::MyInt32>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<std::string, thrift::test::MyString>::value));
|
||||
BOOST_STATIC_ASSERT(
|
||||
(boost::is_same<thrift::test::TypedefTestStruct, thrift::test::MyStruct>::value));
|
21
vendor/git.apache.org/thrift.git/lib/cpp/test/UnitTestMain.cpp
generated
vendored
Normal file
21
vendor/git.apache.org/thrift.git/lib/cpp/test/UnitTestMain.cpp
generated
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE thrift
|
||||
#include <boost/test/auto_unit_test.hpp>
|
461
vendor/git.apache.org/thrift.git/lib/cpp/test/ZlibTest.cpp
generated
vendored
Normal file
461
vendor/git.apache.org/thrift.git/lib/cpp/test/ZlibTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,461 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define __STDC_FORMAT_MACROS
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE // needed for getopt_long
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
#include <cstddef>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <thrift/cxxfunctional.h>
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/random.hpp>
|
||||
#include <boost/shared_array.hpp>
|
||||
#include <boost/test/unit_test.hpp>
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
#include <thrift/transport/TZlibTransport.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace apache::thrift::transport;
|
||||
|
||||
boost::mt19937 rng;
|
||||
|
||||
/*
|
||||
* Utility code
|
||||
*/
|
||||
|
||||
class SizeGenerator {
|
||||
public:
|
||||
virtual ~SizeGenerator() {}
|
||||
virtual unsigned int getSize() = 0;
|
||||
};
|
||||
|
||||
class ConstantSizeGenerator : public SizeGenerator {
|
||||
public:
|
||||
ConstantSizeGenerator(unsigned int value) : value_(value) {}
|
||||
virtual unsigned int getSize() { return value_; }
|
||||
|
||||
private:
|
||||
unsigned int value_;
|
||||
};
|
||||
|
||||
class LogNormalSizeGenerator : public SizeGenerator {
|
||||
public:
|
||||
LogNormalSizeGenerator(double mean, double std_dev)
|
||||
: gen_(rng, boost::lognormal_distribution<double>(mean, std_dev)) {}
|
||||
|
||||
virtual unsigned int getSize() {
|
||||
// Loop until we get a size of 1 or more
|
||||
while (true) {
|
||||
unsigned int value = static_cast<unsigned int>(gen_());
|
||||
if (value >= 1) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
boost::variate_generator<boost::mt19937, boost::lognormal_distribution<double> > gen_;
|
||||
};
|
||||
|
||||
boost::shared_array<uint8_t> gen_uniform_buffer(uint32_t buf_len, uint8_t c) {
|
||||
uint8_t* buf = new uint8_t[buf_len];
|
||||
memset(buf, c, buf_len);
|
||||
return boost::shared_array<uint8_t>(buf);
|
||||
}
|
||||
|
||||
boost::shared_array<uint8_t> gen_compressible_buffer(uint32_t buf_len) {
|
||||
uint8_t* buf = new uint8_t[buf_len];
|
||||
|
||||
// Generate small runs of alternately increasing and decreasing bytes
|
||||
boost::uniform_smallint<uint32_t> run_length_distribution(1, 64);
|
||||
boost::uniform_smallint<uint8_t> byte_distribution(0, UINT8_MAX);
|
||||
boost::variate_generator<boost::mt19937, boost::uniform_smallint<uint8_t> >
|
||||
byte_generator(rng, byte_distribution);
|
||||
boost::variate_generator<boost::mt19937, boost::uniform_smallint<uint32_t> >
|
||||
run_len_generator(rng, run_length_distribution);
|
||||
|
||||
uint32_t idx = 0;
|
||||
int8_t step = 1;
|
||||
while (idx < buf_len) {
|
||||
uint32_t run_length = run_len_generator();
|
||||
if (idx + run_length > buf_len) {
|
||||
run_length = buf_len - idx;
|
||||
}
|
||||
|
||||
uint8_t byte = byte_generator();
|
||||
for (uint32_t n = 0; n < run_length; ++n) {
|
||||
buf[idx] = byte;
|
||||
++idx;
|
||||
byte += step;
|
||||
}
|
||||
|
||||
step *= -1;
|
||||
}
|
||||
|
||||
return boost::shared_array<uint8_t>(buf);
|
||||
}
|
||||
|
||||
boost::shared_array<uint8_t> gen_random_buffer(uint32_t buf_len) {
|
||||
uint8_t* buf = new uint8_t[buf_len];
|
||||
|
||||
boost::uniform_smallint<uint8_t> distribution(0, UINT8_MAX);
|
||||
boost::variate_generator<boost::mt19937, boost::uniform_smallint<uint8_t> >
|
||||
generator(rng, distribution);
|
||||
|
||||
for (uint32_t n = 0; n < buf_len; ++n) {
|
||||
buf[n] = generator();
|
||||
}
|
||||
|
||||
return boost::shared_array<uint8_t>(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test functions
|
||||
*/
|
||||
|
||||
void test_write_then_read(const boost::shared_array<uint8_t> buf, uint32_t buf_len) {
|
||||
boost::shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
|
||||
boost::shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf));
|
||||
zlib_trans->write(buf.get(), buf_len);
|
||||
zlib_trans->finish();
|
||||
|
||||
boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]);
|
||||
uint32_t got = zlib_trans->readAll(mirror.get(), buf_len);
|
||||
BOOST_REQUIRE_EQUAL(got, buf_len);
|
||||
BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0);
|
||||
zlib_trans->verifyChecksum();
|
||||
}
|
||||
|
||||
void test_separate_checksum(const boost::shared_array<uint8_t> buf, uint32_t buf_len) {
|
||||
// This one is tricky. I separate the last byte of the stream out
|
||||
// into a separate crbuf_. The last byte is part of the checksum,
|
||||
// so the entire read goes fine, but when I go to verify the checksum
|
||||
// it isn't there. The original implementation complained that
|
||||
// the stream was not complete. I'm about to go fix that.
|
||||
// It worked. Awesome.
|
||||
boost::shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
|
||||
boost::shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf));
|
||||
zlib_trans->write(buf.get(), buf_len);
|
||||
zlib_trans->finish();
|
||||
string tmp_buf;
|
||||
membuf->appendBufferToString(tmp_buf);
|
||||
zlib_trans.reset(new TZlibTransport(membuf,
|
||||
TZlibTransport::DEFAULT_URBUF_SIZE,
|
||||
static_cast<uint32_t>(tmp_buf.length() - 1)));
|
||||
|
||||
boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]);
|
||||
uint32_t got = zlib_trans->readAll(mirror.get(), buf_len);
|
||||
BOOST_REQUIRE_EQUAL(got, buf_len);
|
||||
BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0);
|
||||
zlib_trans->verifyChecksum();
|
||||
}
|
||||
|
||||
void test_incomplete_checksum(const boost::shared_array<uint8_t> buf, uint32_t buf_len) {
|
||||
// Make sure we still get that "not complete" error if
|
||||
// it really isn't complete.
|
||||
boost::shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
|
||||
boost::shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf));
|
||||
zlib_trans->write(buf.get(), buf_len);
|
||||
zlib_trans->finish();
|
||||
string tmp_buf;
|
||||
membuf->appendBufferToString(tmp_buf);
|
||||
tmp_buf.erase(tmp_buf.length() - 1);
|
||||
membuf->resetBuffer(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(tmp_buf.data())),
|
||||
static_cast<uint32_t>(tmp_buf.length()));
|
||||
|
||||
boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]);
|
||||
uint32_t got = zlib_trans->readAll(mirror.get(), buf_len);
|
||||
BOOST_REQUIRE_EQUAL(got, buf_len);
|
||||
BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0);
|
||||
try {
|
||||
zlib_trans->verifyChecksum();
|
||||
BOOST_ERROR("verifyChecksum() did not report an error");
|
||||
} catch (TTransportException& ex) {
|
||||
BOOST_CHECK_EQUAL(ex.getType(), TTransportException::CORRUPTED_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
void test_read_write_mix(const boost::shared_array<uint8_t> buf,
|
||||
uint32_t buf_len,
|
||||
const boost::shared_ptr<SizeGenerator>& write_gen,
|
||||
const boost::shared_ptr<SizeGenerator>& read_gen) {
|
||||
// Try it with a mix of read/write sizes.
|
||||
boost::shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
|
||||
boost::shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf));
|
||||
unsigned int tot;
|
||||
|
||||
tot = 0;
|
||||
while (tot < buf_len) {
|
||||
uint32_t write_len = write_gen->getSize();
|
||||
if (tot + write_len > buf_len) {
|
||||
write_len = buf_len - tot;
|
||||
}
|
||||
zlib_trans->write(buf.get() + tot, write_len);
|
||||
tot += write_len;
|
||||
}
|
||||
|
||||
zlib_trans->finish();
|
||||
|
||||
tot = 0;
|
||||
boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]);
|
||||
while (tot < buf_len) {
|
||||
uint32_t read_len = read_gen->getSize();
|
||||
uint32_t expected_read_len = read_len;
|
||||
if (tot + read_len > buf_len) {
|
||||
expected_read_len = buf_len - tot;
|
||||
}
|
||||
uint32_t got = zlib_trans->read(mirror.get() + tot, read_len);
|
||||
BOOST_REQUIRE_LE(got, expected_read_len);
|
||||
BOOST_REQUIRE_NE(got, (uint32_t)0);
|
||||
tot += got;
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL(memcmp(mirror.get(), buf.get(), buf_len), 0);
|
||||
zlib_trans->verifyChecksum();
|
||||
}
|
||||
|
||||
void test_invalid_checksum(const boost::shared_array<uint8_t> buf, uint32_t buf_len) {
|
||||
// Verify checksum checking.
|
||||
boost::shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
|
||||
boost::shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf));
|
||||
zlib_trans->write(buf.get(), buf_len);
|
||||
zlib_trans->finish();
|
||||
string tmp_buf;
|
||||
membuf->appendBufferToString(tmp_buf);
|
||||
// Modify a byte at the end of the buffer (part of the checksum).
|
||||
// On rare occasions, modifying a byte in the middle of the buffer
|
||||
// isn't caught by the checksum.
|
||||
//
|
||||
// (This happens especially often for the uniform buffer. The
|
||||
// re-inflated data is correct, however. I suspect in this case that
|
||||
// we're more likely to modify bytes that are part of zlib metadata
|
||||
// instead of the actual compressed data.)
|
||||
//
|
||||
// I've also seen some failure scenarios where a checksum failure isn't
|
||||
// reported, but zlib keeps trying to decode past the end of the data.
|
||||
// (When this occurs, verifyChecksum() throws an exception indicating
|
||||
// that the end of the data hasn't been reached.) I haven't seen this
|
||||
// error when only modifying checksum bytes.
|
||||
int index = static_cast<int>(tmp_buf.size() - 1);
|
||||
tmp_buf[index]++;
|
||||
membuf->resetBuffer(const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(tmp_buf.data())),
|
||||
static_cast<uint32_t>(tmp_buf.length()));
|
||||
|
||||
boost::shared_array<uint8_t> mirror(new uint8_t[buf_len]);
|
||||
try {
|
||||
zlib_trans->readAll(mirror.get(), buf_len);
|
||||
zlib_trans->verifyChecksum();
|
||||
BOOST_ERROR("verifyChecksum() did not report an error");
|
||||
} catch (TZlibTransportException& ex) {
|
||||
BOOST_CHECK_EQUAL(ex.getType(), TTransportException::INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
void test_write_after_flush(const boost::shared_array<uint8_t> buf, uint32_t buf_len) {
|
||||
// write some data
|
||||
boost::shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
|
||||
boost::shared_ptr<TZlibTransport> zlib_trans(new TZlibTransport(membuf));
|
||||
zlib_trans->write(buf.get(), buf_len);
|
||||
|
||||
// call finish()
|
||||
zlib_trans->finish();
|
||||
|
||||
// make sure write() throws an error
|
||||
try {
|
||||
uint8_t write_buf[] = "a";
|
||||
zlib_trans->write(write_buf, 1);
|
||||
BOOST_ERROR("write() after finish() did not raise an exception");
|
||||
} catch (TTransportException& ex) {
|
||||
BOOST_CHECK_EQUAL(ex.getType(), TTransportException::BAD_ARGS);
|
||||
}
|
||||
|
||||
// make sure flush() throws an error
|
||||
try {
|
||||
zlib_trans->flush();
|
||||
BOOST_ERROR("flush() after finish() did not raise an exception");
|
||||
} catch (TTransportException& ex) {
|
||||
BOOST_CHECK_EQUAL(ex.getType(), TTransportException::BAD_ARGS);
|
||||
}
|
||||
|
||||
// make sure finish() throws an error
|
||||
try {
|
||||
zlib_trans->finish();
|
||||
BOOST_ERROR("finish() after finish() did not raise an exception");
|
||||
} catch (TTransportException& ex) {
|
||||
BOOST_CHECK_EQUAL(ex.getType(), TTransportException::BAD_ARGS);
|
||||
}
|
||||
}
|
||||
|
||||
void test_no_write() {
|
||||
// Verify that no data is written to the underlying transport if we
|
||||
// never write data to the TZlibTransport.
|
||||
boost::shared_ptr<TMemoryBuffer> membuf(new TMemoryBuffer());
|
||||
{
|
||||
// Create a TZlibTransport object, and immediately destroy it
|
||||
// when it goes out of scope.
|
||||
TZlibTransport w_zlib_trans(membuf);
|
||||
}
|
||||
|
||||
BOOST_CHECK_EQUAL(membuf->available_read(), (uint32_t)0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialization
|
||||
*/
|
||||
|
||||
#if (BOOST_VERSION >= 105900)
|
||||
#define ADD_TEST_CASE(suite, name, _FUNC, ...) \
|
||||
do { \
|
||||
::std::ostringstream name_ss; \
|
||||
name_ss << name << "-" << BOOST_STRINGIZE(_FUNC); \
|
||||
boost::function<void ()> test_func = ::apache::thrift::stdcxx::bind(_FUNC, ##__VA_ARGS__); \
|
||||
::boost::unit_test::test_case* tc \
|
||||
= ::boost::unit_test::make_test_case(test_func, name_ss.str(), __FILE__, __LINE__); \
|
||||
(suite)->add(tc); \
|
||||
} while (0)
|
||||
#else
|
||||
#define ADD_TEST_CASE(suite, name, _FUNC, ...) \
|
||||
do { \
|
||||
::std::ostringstream name_ss; \
|
||||
name_ss << name << "-" << BOOST_STRINGIZE(_FUNC); \
|
||||
::boost::unit_test::test_case* tc \
|
||||
= ::boost::unit_test::make_test_case(::apache::thrift::stdcxx::bind(_FUNC, \
|
||||
##__VA_ARGS__), \
|
||||
name_ss.str()); \
|
||||
(suite)->add(tc); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
void add_tests(boost::unit_test::test_suite* suite,
|
||||
const boost::shared_array<uint8_t>& buf,
|
||||
uint32_t buf_len,
|
||||
const char* name) {
|
||||
ADD_TEST_CASE(suite, name, test_write_then_read, buf, buf_len);
|
||||
ADD_TEST_CASE(suite, name, test_separate_checksum, buf, buf_len);
|
||||
ADD_TEST_CASE(suite, name, test_incomplete_checksum, buf, buf_len);
|
||||
ADD_TEST_CASE(suite, name, test_invalid_checksum, buf, buf_len);
|
||||
ADD_TEST_CASE(suite, name, test_write_after_flush, buf, buf_len);
|
||||
|
||||
boost::shared_ptr<SizeGenerator> size_32k(new ConstantSizeGenerator(1 << 15));
|
||||
boost::shared_ptr<SizeGenerator> size_lognormal(new LogNormalSizeGenerator(20, 30));
|
||||
ADD_TEST_CASE(suite, name << "-constant", test_read_write_mix, buf, buf_len, size_32k, size_32k);
|
||||
ADD_TEST_CASE(suite,
|
||||
name << "-lognormal-write",
|
||||
test_read_write_mix,
|
||||
buf,
|
||||
buf_len,
|
||||
size_lognormal,
|
||||
size_32k);
|
||||
ADD_TEST_CASE(suite,
|
||||
name << "-lognormal-read",
|
||||
test_read_write_mix,
|
||||
buf,
|
||||
buf_len,
|
||||
size_32k,
|
||||
size_lognormal);
|
||||
ADD_TEST_CASE(suite,
|
||||
name << "-lognormal-both",
|
||||
test_read_write_mix,
|
||||
buf,
|
||||
buf_len,
|
||||
size_lognormal,
|
||||
size_lognormal);
|
||||
|
||||
// Test with a random size distribution,
|
||||
// but use the exact same distribution for reading as for writing.
|
||||
//
|
||||
// Because the SizeGenerator makes a copy of the random number generator,
|
||||
// both SizeGenerators should return the exact same set of values, since they
|
||||
// both start with random number generators in the same state.
|
||||
boost::shared_ptr<SizeGenerator> write_size_gen(new LogNormalSizeGenerator(20, 30));
|
||||
boost::shared_ptr<SizeGenerator> read_size_gen(new LogNormalSizeGenerator(20, 30));
|
||||
ADD_TEST_CASE(suite,
|
||||
name << "-lognormal-same-distribution",
|
||||
test_read_write_mix,
|
||||
buf,
|
||||
buf_len,
|
||||
write_size_gen,
|
||||
read_size_gen);
|
||||
}
|
||||
|
||||
void print_usage(FILE* f, const char* argv0) {
|
||||
fprintf(f, "Usage: %s [boost_options] [options]\n", argv0);
|
||||
fprintf(f, "Options:\n");
|
||||
fprintf(f, " --seed=<N>, -s <N>\n");
|
||||
fprintf(f, " --help\n");
|
||||
}
|
||||
|
||||
#ifdef BOOST_TEST_DYN_LINK
|
||||
bool init_unit_test_suite() {
|
||||
uint32_t seed = static_cast<uint32_t>(time(NULL));
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
printf("seed: %" PRIu32 "\n", seed);
|
||||
#endif
|
||||
rng.seed(seed);
|
||||
|
||||
boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite();
|
||||
suite->p_name.value = "ZlibTest";
|
||||
|
||||
uint32_t buf_len = 1024 * 32;
|
||||
add_tests(suite, gen_uniform_buffer(buf_len, 'a'), buf_len, "uniform");
|
||||
add_tests(suite, gen_compressible_buffer(buf_len), buf_len, "compressible");
|
||||
add_tests(suite, gen_random_buffer(buf_len), buf_len, "random");
|
||||
|
||||
suite->add(BOOST_TEST_CASE(test_no_write));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main( int argc, char* argv[] ) {
|
||||
return ::boost::unit_test::unit_test_main(&init_unit_test_suite,argc,argv);
|
||||
}
|
||||
#else
|
||||
boost::unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) {
|
||||
THRIFT_UNUSED_VARIABLE(argc);
|
||||
THRIFT_UNUSED_VARIABLE(argv);
|
||||
uint32_t seed = static_cast<uint32_t>(time(NULL));
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
printf("seed: %" PRIu32 "\n", seed);
|
||||
#endif
|
||||
rng.seed(seed);
|
||||
|
||||
boost::unit_test::test_suite* suite = &boost::unit_test::framework::master_test_suite();
|
||||
suite->p_name.value = "ZlibTest";
|
||||
|
||||
uint32_t buf_len = 1024 * 32;
|
||||
add_tests(suite, gen_uniform_buffer(buf_len, 'a'), buf_len, "uniform");
|
||||
add_tests(suite, gen_compressible_buffer(buf_len), buf_len, "compressible");
|
||||
add_tests(suite, gen_random_buffer(buf_len), buf_len, "random");
|
||||
|
||||
suite->add(BOOST_TEST_CASE(test_no_write));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
189
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/Tests.cpp
generated
vendored
Normal file
189
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/Tests.cpp
generated
vendored
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "ThreadFactoryTests.h"
|
||||
#include "TimerManagerTests.h"
|
||||
#include "ThreadManagerTests.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
std::string arg;
|
||||
|
||||
std::vector<std::string> args(argc - 1 > 1 ? argc - 1 : 1);
|
||||
|
||||
args[0] = "all";
|
||||
|
||||
for (int ix = 1; ix < argc; ix++) {
|
||||
args[ix - 1] = std::string(argv[ix]);
|
||||
}
|
||||
|
||||
bool runAll = args[0].compare("all") == 0;
|
||||
|
||||
if (runAll || args[0].compare("thread-factory") == 0) {
|
||||
|
||||
ThreadFactoryTests threadFactoryTests;
|
||||
|
||||
std::cout << "ThreadFactory tests..." << std::endl;
|
||||
|
||||
int reapLoops = 20;
|
||||
int reapCount = 1000;
|
||||
size_t floodLoops = 3;
|
||||
size_t floodCount = 20000;
|
||||
|
||||
std::cout << "\t\tThreadFactory reap N threads test: N = " << reapLoops << "x" << reapCount << std::endl;
|
||||
|
||||
if (!threadFactoryTests.reapNThreads(reapLoops, reapCount)) {
|
||||
std::cerr << "\t\ttThreadFactory reap N threads FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "\t\tThreadFactory flood N threads test: N = " << floodLoops << "x" << floodCount << std::endl;
|
||||
|
||||
if (!threadFactoryTests.floodNTest(floodLoops, floodCount)) {
|
||||
std::cerr << "\t\ttThreadFactory flood N threads FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "\t\tThreadFactory synchronous start test" << std::endl;
|
||||
|
||||
if (!threadFactoryTests.synchStartTest()) {
|
||||
std::cerr << "\t\ttThreadFactory synchronous start FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "\t\tThreadFactory monitor timeout test" << std::endl;
|
||||
|
||||
if (!threadFactoryTests.monitorTimeoutTest()) {
|
||||
std::cerr << "\t\ttThreadFactory monitor timeout FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (runAll || args[0].compare("util") == 0) {
|
||||
|
||||
std::cout << "Util tests..." << std::endl;
|
||||
|
||||
std::cout << "\t\tUtil minimum time" << std::endl;
|
||||
|
||||
int64_t time00 = Util::currentTime();
|
||||
int64_t time01 = Util::currentTime();
|
||||
|
||||
std::cout << "\t\t\tMinimum time: " << time01 - time00 << "ms" << std::endl;
|
||||
|
||||
time00 = Util::currentTime();
|
||||
time01 = time00;
|
||||
size_t count = 0;
|
||||
|
||||
while (time01 < time00 + 10) {
|
||||
count++;
|
||||
time01 = Util::currentTime();
|
||||
}
|
||||
|
||||
std::cout << "\t\t\tscall per ms: " << count / (time01 - time00) << std::endl;
|
||||
}
|
||||
|
||||
if (runAll || args[0].compare("timer-manager") == 0) {
|
||||
|
||||
std::cout << "TimerManager tests..." << std::endl;
|
||||
|
||||
std::cout << "\t\tTimerManager test00" << std::endl;
|
||||
|
||||
TimerManagerTests timerManagerTests;
|
||||
|
||||
if (!timerManagerTests.test00()) {
|
||||
std::cerr << "\t\tTimerManager tests FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (runAll || args[0].compare("thread-manager") == 0) {
|
||||
|
||||
std::cout << "ThreadManager tests..." << std::endl;
|
||||
|
||||
{
|
||||
size_t workerCount = 100;
|
||||
size_t taskCount = 50000;
|
||||
int64_t delay = 10LL;
|
||||
|
||||
ThreadManagerTests threadManagerTests;
|
||||
|
||||
std::cout << "\t\tThreadManager api test:" << std::endl;
|
||||
|
||||
if (!threadManagerTests.apiTest()) {
|
||||
std::cerr << "\t\tThreadManager apiTest FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "\t\tThreadManager load test: worker count: " << workerCount
|
||||
<< " task count: " << taskCount << " delay: " << delay << std::endl;
|
||||
|
||||
if (!threadManagerTests.loadTest(taskCount, delay, workerCount)) {
|
||||
std::cerr << "\t\tThreadManager loadTest FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "\t\tThreadManager block test: worker count: " << workerCount
|
||||
<< " delay: " << delay << std::endl;
|
||||
|
||||
if (!threadManagerTests.blockTest(delay, workerCount)) {
|
||||
std::cerr << "\t\tThreadManager blockTest FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (runAll || args[0].compare("thread-manager-benchmark") == 0) {
|
||||
|
||||
std::cout << "ThreadManager benchmark tests..." << std::endl;
|
||||
|
||||
{
|
||||
|
||||
size_t minWorkerCount = 2;
|
||||
|
||||
size_t maxWorkerCount = 64;
|
||||
|
||||
size_t tasksPerWorker = 1000;
|
||||
|
||||
int64_t delay = 5LL;
|
||||
|
||||
for (size_t workerCount = minWorkerCount; workerCount < maxWorkerCount; workerCount *= 4) {
|
||||
|
||||
size_t taskCount = workerCount * tasksPerWorker;
|
||||
|
||||
std::cout << "\t\tThreadManager load test: worker count: " << workerCount
|
||||
<< " task count: " << taskCount << " delay: " << delay << std::endl;
|
||||
|
||||
ThreadManagerTests threadManagerTests;
|
||||
|
||||
if (!threadManagerTests.loadTest(taskCount, delay, workerCount))
|
||||
{
|
||||
std::cerr << "\t\tThreadManager loadTest FAILED" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "ALL TESTS PASSED" << std::endl;
|
||||
return 0;
|
||||
}
|
313
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/ThreadFactoryTests.h
generated
vendored
Normal file
313
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/ThreadFactoryTests.h
generated
vendored
Normal file
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <thrift/thrift-config.h>
|
||||
#include <thrift/concurrency/Thread.h>
|
||||
#include <thrift/concurrency/PlatformThreadFactory.h>
|
||||
#include <thrift/concurrency/Monitor.h>
|
||||
#include <thrift/concurrency/Util.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <set>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
namespace test {
|
||||
|
||||
using boost::shared_ptr;
|
||||
using namespace apache::thrift::concurrency;
|
||||
|
||||
/**
|
||||
* ThreadManagerTests class
|
||||
*
|
||||
* @version $Id:$
|
||||
*/
|
||||
class ThreadFactoryTests {
|
||||
|
||||
public:
|
||||
/**
|
||||
* Reap N threads
|
||||
*/
|
||||
class ReapNTask : public Runnable {
|
||||
|
||||
public:
|
||||
ReapNTask(Monitor& monitor, int& activeCount) : _monitor(monitor), _count(activeCount) {}
|
||||
|
||||
void run() {
|
||||
Synchronized s(_monitor);
|
||||
|
||||
_count--;
|
||||
|
||||
// std::cout << "\t\t\tthread count: " << _count << std::endl;
|
||||
|
||||
if (_count == 0) {
|
||||
_monitor.notify();
|
||||
}
|
||||
}
|
||||
|
||||
Monitor& _monitor;
|
||||
|
||||
int& _count;
|
||||
};
|
||||
|
||||
bool reapNThreads(int loop = 1, int count = 10) {
|
||||
|
||||
PlatformThreadFactory threadFactory = PlatformThreadFactory();
|
||||
|
||||
shared_ptr<Monitor> monitor(new Monitor);
|
||||
|
||||
for (int lix = 0; lix < loop; lix++) {
|
||||
|
||||
int* activeCount = new int(count);
|
||||
|
||||
std::set<shared_ptr<Thread> > threads;
|
||||
|
||||
int tix;
|
||||
|
||||
for (tix = 0; tix < count; tix++) {
|
||||
try {
|
||||
threads.insert(
|
||||
threadFactory.newThread(shared_ptr<Runnable>(new ReapNTask(*monitor, *activeCount))));
|
||||
} catch (SystemResourceException& e) {
|
||||
std::cout << "\t\t\tfailed to create " << lix* count + tix << " thread " << e.what()
|
||||
<< std::endl;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
tix = 0;
|
||||
for (std::set<shared_ptr<Thread> >::const_iterator thread = threads.begin();
|
||||
thread != threads.end();
|
||||
tix++, ++thread) {
|
||||
|
||||
try {
|
||||
(*thread)->start();
|
||||
} catch (SystemResourceException& e) {
|
||||
std::cout << "\t\t\tfailed to start " << lix* count + tix << " thread " << e.what()
|
||||
<< std::endl;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Synchronized s(*monitor);
|
||||
while (*activeCount > 0) {
|
||||
monitor->wait(1000);
|
||||
}
|
||||
}
|
||||
delete activeCount;
|
||||
std::cout << "\t\t\treaped " << lix* count << " threads" << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "\t\t\tSuccess!" << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class SynchStartTask : public Runnable {
|
||||
|
||||
public:
|
||||
enum STATE { UNINITIALIZED, STARTING, STARTED, STOPPING, STOPPED };
|
||||
|
||||
SynchStartTask(Monitor& monitor, volatile STATE& state) : _monitor(monitor), _state(state) {}
|
||||
|
||||
void run() {
|
||||
{
|
||||
Synchronized s(_monitor);
|
||||
if (_state == SynchStartTask::STARTING) {
|
||||
_state = SynchStartTask::STARTED;
|
||||
_monitor.notify();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Synchronized s(_monitor);
|
||||
while (_state == SynchStartTask::STARTED) {
|
||||
_monitor.wait();
|
||||
}
|
||||
|
||||
if (_state == SynchStartTask::STOPPING) {
|
||||
_state = SynchStartTask::STOPPED;
|
||||
_monitor.notifyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Monitor& _monitor;
|
||||
volatile STATE& _state;
|
||||
};
|
||||
|
||||
bool synchStartTest() {
|
||||
|
||||
Monitor monitor;
|
||||
|
||||
SynchStartTask::STATE state = SynchStartTask::UNINITIALIZED;
|
||||
|
||||
shared_ptr<SynchStartTask> task
|
||||
= shared_ptr<SynchStartTask>(new SynchStartTask(monitor, state));
|
||||
|
||||
PlatformThreadFactory threadFactory = PlatformThreadFactory();
|
||||
|
||||
shared_ptr<Thread> thread = threadFactory.newThread(task);
|
||||
|
||||
if (state == SynchStartTask::UNINITIALIZED) {
|
||||
|
||||
state = SynchStartTask::STARTING;
|
||||
|
||||
thread->start();
|
||||
}
|
||||
|
||||
{
|
||||
Synchronized s(monitor);
|
||||
while (state == SynchStartTask::STARTING) {
|
||||
monitor.wait();
|
||||
}
|
||||
}
|
||||
|
||||
assert(state != SynchStartTask::STARTING);
|
||||
|
||||
{
|
||||
Synchronized s(monitor);
|
||||
|
||||
try {
|
||||
monitor.wait(100);
|
||||
} catch (TimedOutException&) {
|
||||
}
|
||||
|
||||
if (state == SynchStartTask::STARTED) {
|
||||
|
||||
state = SynchStartTask::STOPPING;
|
||||
|
||||
monitor.notify();
|
||||
}
|
||||
|
||||
while (state == SynchStartTask::STOPPING) {
|
||||
monitor.wait();
|
||||
}
|
||||
}
|
||||
|
||||
assert(state == SynchStartTask::STOPPED);
|
||||
|
||||
bool success = true;
|
||||
|
||||
std::cout << "\t\t\t" << (success ? "Success" : "Failure") << "!" << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The only guarantee a monitor timeout can give you is that
|
||||
* it will take "at least" as long as the timeout, no less.
|
||||
* There is absolutely no guarantee around regaining execution
|
||||
* near the timeout. On a busy system (like inside a third party
|
||||
* CI environment) it could take quite a bit longer than the
|
||||
* requested timeout, and that's ok.
|
||||
*/
|
||||
|
||||
bool monitorTimeoutTest(int64_t count = 1000, int64_t timeout = 2) {
|
||||
|
||||
Monitor monitor;
|
||||
|
||||
int64_t startTime = Util::currentTime();
|
||||
|
||||
for (int64_t ix = 0; ix < count; ix++) {
|
||||
{
|
||||
Synchronized s(monitor);
|
||||
try {
|
||||
monitor.wait(timeout);
|
||||
} catch (TimedOutException&) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int64_t endTime = Util::currentTime();
|
||||
|
||||
bool success = (endTime - startTime) >= (count * timeout);
|
||||
|
||||
std::cout << "\t\t\t" << (success ? "Success" : "Failure")
|
||||
<< ": minimum required time to elapse " << count * timeout
|
||||
<< "ms; actual elapsed time " << endTime - startTime << "ms"
|
||||
<< std::endl;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
class FloodTask : public Runnable {
|
||||
public:
|
||||
FloodTask(const size_t id) : _id(id) {}
|
||||
~FloodTask() {
|
||||
if (_id % 10000 == 0) {
|
||||
std::cout << "\t\tthread " << _id << " done" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void run() {
|
||||
if (_id % 10000 == 0) {
|
||||
std::cout << "\t\tthread " << _id << " started" << std::endl;
|
||||
}
|
||||
}
|
||||
const size_t _id;
|
||||
};
|
||||
|
||||
void foo(PlatformThreadFactory* tf) { (void)tf; }
|
||||
|
||||
bool floodNTest(size_t loop = 1, size_t count = 100000) {
|
||||
|
||||
bool success = false;
|
||||
|
||||
for (size_t lix = 0; lix < loop; lix++) {
|
||||
|
||||
PlatformThreadFactory threadFactory = PlatformThreadFactory();
|
||||
threadFactory.setDetached(true);
|
||||
|
||||
for (size_t tix = 0; tix < count; tix++) {
|
||||
|
||||
try {
|
||||
|
||||
shared_ptr<FloodTask> task(new FloodTask(lix * count + tix));
|
||||
|
||||
shared_ptr<Thread> thread = threadFactory.newThread(task);
|
||||
|
||||
thread->start();
|
||||
|
||||
} catch (TException& e) {
|
||||
|
||||
std::cout << "\t\t\tfailed to start " << lix* count + tix << " thread " << e.what()
|
||||
<< std::endl;
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "\t\t\tflooded " << (lix + 1) * count << " threads" << std::endl;
|
||||
|
||||
success = true;
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency::test
|
685
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/ThreadManagerTests.h
generated
vendored
Normal file
685
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/ThreadManagerTests.h
generated
vendored
Normal file
|
@ -0,0 +1,685 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <thrift/thrift-config.h>
|
||||
#include <thrift/concurrency/ThreadManager.h>
|
||||
#include <thrift/concurrency/PlatformThreadFactory.h>
|
||||
#include <thrift/concurrency/Monitor.h>
|
||||
#include <thrift/concurrency/Util.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
namespace test {
|
||||
|
||||
using namespace apache::thrift::concurrency;
|
||||
|
||||
static std::deque<boost::shared_ptr<Runnable> > m_expired;
|
||||
static void expiredNotifier(boost::shared_ptr<Runnable> runnable)
|
||||
{
|
||||
m_expired.push_back(runnable);
|
||||
}
|
||||
|
||||
static void sleep_(int64_t millisec) {
|
||||
Monitor _sleep;
|
||||
Synchronized s(_sleep);
|
||||
|
||||
try {
|
||||
_sleep.wait(millisec);
|
||||
} catch (TimedOutException&) {
|
||||
;
|
||||
} catch (...) {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
class ThreadManagerTests {
|
||||
|
||||
public:
|
||||
class Task : public Runnable {
|
||||
|
||||
public:
|
||||
Task(Monitor& monitor, size_t& count, int64_t timeout)
|
||||
: _monitor(monitor), _count(count), _timeout(timeout), _startTime(0), _endTime(0), _done(false) {}
|
||||
|
||||
void run() {
|
||||
|
||||
_startTime = Util::currentTime();
|
||||
|
||||
sleep_(_timeout);
|
||||
|
||||
_endTime = Util::currentTime();
|
||||
|
||||
_done = true;
|
||||
|
||||
{
|
||||
Synchronized s(_monitor);
|
||||
|
||||
// std::cout << "Thread " << _count << " completed " << std::endl;
|
||||
|
||||
_count--;
|
||||
if (_count % 10000 == 0) {
|
||||
_monitor.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Monitor& _monitor;
|
||||
size_t& _count;
|
||||
int64_t _timeout;
|
||||
int64_t _startTime;
|
||||
int64_t _endTime;
|
||||
bool _done;
|
||||
Monitor _sleep;
|
||||
};
|
||||
|
||||
/**
|
||||
* Dispatch count tasks, each of which blocks for timeout milliseconds then
|
||||
* completes. Verify that all tasks completed and that thread manager cleans
|
||||
* up properly on delete.
|
||||
*/
|
||||
bool loadTest(size_t count = 100, int64_t timeout = 100LL, size_t workerCount = 4) {
|
||||
|
||||
Monitor monitor;
|
||||
|
||||
size_t activeCount = count;
|
||||
|
||||
shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(workerCount);
|
||||
|
||||
shared_ptr<PlatformThreadFactory> threadFactory
|
||||
= shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory());
|
||||
|
||||
#if !USE_BOOST_THREAD && !USE_STD_THREAD
|
||||
threadFactory->setPriority(PosixThreadFactory::HIGHEST);
|
||||
#endif
|
||||
threadManager->threadFactory(threadFactory);
|
||||
|
||||
threadManager->start();
|
||||
|
||||
std::set<shared_ptr<ThreadManagerTests::Task> > tasks;
|
||||
|
||||
for (size_t ix = 0; ix < count; ix++) {
|
||||
|
||||
tasks.insert(shared_ptr<ThreadManagerTests::Task>(
|
||||
new ThreadManagerTests::Task(monitor, activeCount, timeout)));
|
||||
}
|
||||
|
||||
int64_t time00 = Util::currentTime();
|
||||
|
||||
for (std::set<shared_ptr<ThreadManagerTests::Task> >::iterator ix = tasks.begin();
|
||||
ix != tasks.end();
|
||||
ix++) {
|
||||
|
||||
threadManager->add(*ix);
|
||||
}
|
||||
|
||||
std::cout << "\t\t\t\tloaded " << count << " tasks to execute" << std::endl;
|
||||
|
||||
{
|
||||
Synchronized s(monitor);
|
||||
|
||||
while (activeCount > 0) {
|
||||
std::cout << "\t\t\t\tactiveCount = " << activeCount << std::endl;
|
||||
monitor.wait();
|
||||
}
|
||||
}
|
||||
|
||||
int64_t time01 = Util::currentTime();
|
||||
|
||||
int64_t firstTime = 9223372036854775807LL;
|
||||
int64_t lastTime = 0;
|
||||
|
||||
double averageTime = 0;
|
||||
int64_t minTime = 9223372036854775807LL;
|
||||
int64_t maxTime = 0;
|
||||
|
||||
for (std::set<shared_ptr<ThreadManagerTests::Task> >::iterator ix = tasks.begin();
|
||||
ix != tasks.end();
|
||||
ix++) {
|
||||
|
||||
shared_ptr<ThreadManagerTests::Task> task = *ix;
|
||||
|
||||
int64_t delta = task->_endTime - task->_startTime;
|
||||
|
||||
assert(delta > 0);
|
||||
|
||||
if (task->_startTime < firstTime) {
|
||||
firstTime = task->_startTime;
|
||||
}
|
||||
|
||||
if (task->_endTime > lastTime) {
|
||||
lastTime = task->_endTime;
|
||||
}
|
||||
|
||||
if (delta < minTime) {
|
||||
minTime = delta;
|
||||
}
|
||||
|
||||
if (delta > maxTime) {
|
||||
maxTime = delta;
|
||||
}
|
||||
|
||||
averageTime += delta;
|
||||
}
|
||||
|
||||
averageTime /= count;
|
||||
|
||||
std::cout << "\t\t\tfirst start: " << firstTime << " Last end: " << lastTime
|
||||
<< " min: " << minTime << "ms max: " << maxTime << "ms average: " << averageTime
|
||||
<< "ms" << std::endl;
|
||||
|
||||
bool success = (time01 - time00) >= ((int64_t)count * timeout) / (int64_t)workerCount;
|
||||
|
||||
std::cout << "\t\t\t" << (success ? "Success" : "Failure")
|
||||
<< "! expected time: " << ((int64_t)count * timeout) / (int64_t)workerCount << "ms elapsed time: " << time01 - time00
|
||||
<< "ms" << std::endl;
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
class BlockTask : public Runnable {
|
||||
|
||||
public:
|
||||
BlockTask(Monitor& entryMonitor, Monitor& blockMonitor, bool& blocked, Monitor& doneMonitor, size_t& count)
|
||||
: _entryMonitor(entryMonitor), _entered(false), _blockMonitor(blockMonitor), _blocked(blocked), _doneMonitor(doneMonitor), _count(count) {}
|
||||
|
||||
void run() {
|
||||
{
|
||||
Synchronized s(_entryMonitor);
|
||||
_entered = true;
|
||||
_entryMonitor.notify();
|
||||
}
|
||||
|
||||
{
|
||||
Synchronized s(_blockMonitor);
|
||||
while (_blocked) {
|
||||
_blockMonitor.wait();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Synchronized s(_doneMonitor);
|
||||
if (--_count == 0) {
|
||||
_doneMonitor.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Monitor& _entryMonitor;
|
||||
bool _entered;
|
||||
Monitor& _blockMonitor;
|
||||
bool& _blocked;
|
||||
Monitor& _doneMonitor;
|
||||
size_t& _count;
|
||||
};
|
||||
|
||||
/**
|
||||
* Block test. Create pendingTaskCountMax tasks. Verify that we block adding the
|
||||
* pendingTaskCountMax + 1th task. Verify that we unblock when a task completes */
|
||||
|
||||
bool blockTest(int64_t timeout = 100LL, size_t workerCount = 2) {
|
||||
(void)timeout;
|
||||
bool success = false;
|
||||
|
||||
try {
|
||||
|
||||
Monitor entryMonitor; // not used by this test
|
||||
Monitor blockMonitor;
|
||||
bool blocked[] = {true, true, true};
|
||||
Monitor doneMonitor;
|
||||
|
||||
size_t pendingTaskMaxCount = workerCount;
|
||||
|
||||
size_t activeCounts[] = {workerCount, pendingTaskMaxCount, 1};
|
||||
|
||||
shared_ptr<ThreadManager> threadManager
|
||||
= ThreadManager::newSimpleThreadManager(workerCount, pendingTaskMaxCount);
|
||||
|
||||
shared_ptr<PlatformThreadFactory> threadFactory
|
||||
= shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory());
|
||||
|
||||
#if !USE_BOOST_THREAD && !USE_STD_THREAD
|
||||
threadFactory->setPriority(PosixThreadFactory::HIGHEST);
|
||||
#endif
|
||||
threadManager->threadFactory(threadFactory);
|
||||
|
||||
threadManager->start();
|
||||
|
||||
std::vector<shared_ptr<ThreadManagerTests::BlockTask> > tasks;
|
||||
tasks.reserve(workerCount + pendingTaskMaxCount);
|
||||
|
||||
for (size_t ix = 0; ix < workerCount; ix++) {
|
||||
|
||||
tasks.push_back(shared_ptr<ThreadManagerTests::BlockTask>(
|
||||
new ThreadManagerTests::BlockTask(entryMonitor, blockMonitor, blocked[0], doneMonitor, activeCounts[0])));
|
||||
}
|
||||
|
||||
for (size_t ix = 0; ix < pendingTaskMaxCount; ix++) {
|
||||
|
||||
tasks.push_back(shared_ptr<ThreadManagerTests::BlockTask>(
|
||||
new ThreadManagerTests::BlockTask(entryMonitor, blockMonitor, blocked[1], doneMonitor, activeCounts[1])));
|
||||
}
|
||||
|
||||
for (std::vector<shared_ptr<ThreadManagerTests::BlockTask> >::iterator ix = tasks.begin();
|
||||
ix != tasks.end();
|
||||
ix++) {
|
||||
threadManager->add(*ix);
|
||||
}
|
||||
|
||||
if (!(success = (threadManager->totalTaskCount() == pendingTaskMaxCount + workerCount))) {
|
||||
throw TException("Unexpected pending task count");
|
||||
}
|
||||
|
||||
shared_ptr<ThreadManagerTests::BlockTask> extraTask(
|
||||
new ThreadManagerTests::BlockTask(entryMonitor, blockMonitor, blocked[2], doneMonitor, activeCounts[2]));
|
||||
|
||||
try {
|
||||
threadManager->add(extraTask, 1);
|
||||
throw TException("Unexpected success adding task in excess of pending task count");
|
||||
} catch (TooManyPendingTasksException&) {
|
||||
throw TException("Should have timed out adding task in excess of pending task count");
|
||||
} catch (TimedOutException&) {
|
||||
// Expected result
|
||||
}
|
||||
|
||||
try {
|
||||
threadManager->add(extraTask, -1);
|
||||
throw TException("Unexpected success adding task in excess of pending task count");
|
||||
} catch (TimedOutException&) {
|
||||
throw TException("Unexpected timeout adding task in excess of pending task count");
|
||||
} catch (TooManyPendingTasksException&) {
|
||||
// Expected result
|
||||
}
|
||||
|
||||
std::cout << "\t\t\t"
|
||||
<< "Pending tasks " << threadManager->pendingTaskCount() << std::endl;
|
||||
|
||||
{
|
||||
Synchronized s(blockMonitor);
|
||||
blocked[0] = false;
|
||||
blockMonitor.notifyAll();
|
||||
}
|
||||
|
||||
{
|
||||
Synchronized s(doneMonitor);
|
||||
while (activeCounts[0] != 0) {
|
||||
doneMonitor.wait();
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "\t\t\t"
|
||||
<< "Pending tasks " << threadManager->pendingTaskCount() << std::endl;
|
||||
|
||||
try {
|
||||
threadManager->add(extraTask, 1);
|
||||
} catch (TimedOutException&) {
|
||||
std::cout << "\t\t\t"
|
||||
<< "add timed out unexpectedly" << std::endl;
|
||||
throw TException("Unexpected timeout adding task");
|
||||
|
||||
} catch (TooManyPendingTasksException&) {
|
||||
std::cout << "\t\t\t"
|
||||
<< "add encountered too many pending exepctions" << std::endl;
|
||||
throw TException("Unexpected timeout adding task");
|
||||
}
|
||||
|
||||
// Wake up tasks that were pending before and wait for them to complete
|
||||
|
||||
{
|
||||
Synchronized s(blockMonitor);
|
||||
blocked[1] = false;
|
||||
blockMonitor.notifyAll();
|
||||
}
|
||||
|
||||
{
|
||||
Synchronized s(doneMonitor);
|
||||
while (activeCounts[1] != 0) {
|
||||
doneMonitor.wait();
|
||||
}
|
||||
}
|
||||
|
||||
// Wake up the extra task and wait for it to complete
|
||||
|
||||
{
|
||||
Synchronized s(blockMonitor);
|
||||
blocked[2] = false;
|
||||
blockMonitor.notifyAll();
|
||||
}
|
||||
|
||||
{
|
||||
Synchronized s(doneMonitor);
|
||||
while (activeCounts[2] != 0) {
|
||||
doneMonitor.wait();
|
||||
}
|
||||
}
|
||||
|
||||
threadManager->stop();
|
||||
|
||||
if (!(success = (threadManager->totalTaskCount() == 0))) {
|
||||
throw TException("Unexpected total task count");
|
||||
}
|
||||
|
||||
} catch (TException& e) {
|
||||
std::cout << "ERROR: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "\t\t\t" << (success ? "Success" : "Failure") << std::endl;
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
bool apiTest() {
|
||||
|
||||
// prove currentTime has milliseconds granularity since many other things depend on it
|
||||
int64_t a = Util::currentTime();
|
||||
sleep_(100);
|
||||
int64_t b = Util::currentTime();
|
||||
if (b - a < 50 || b - a > 150) {
|
||||
std::cerr << "\t\t\texpected 100ms gap, found " << (b-a) << "ms gap instead." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !USE_BOOST_THREAD && !USE_STD_THREAD
|
||||
// test once with a detached thread factory and once with a joinable thread factory
|
||||
|
||||
shared_ptr<PosixThreadFactory> threadFactory
|
||||
= shared_ptr<PosixThreadFactory>(new PosixThreadFactory(false));
|
||||
|
||||
std::cout << "\t\t\tapiTest with joinable thread factory" << std::endl;
|
||||
if (!apiTestWithThreadFactory(threadFactory)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
threadFactory.reset(new PosixThreadFactory(true));
|
||||
std::cout << "\t\t\tapiTest with detached thread factory" << std::endl;
|
||||
return apiTestWithThreadFactory(threadFactory);
|
||||
#else
|
||||
return apiTestWithThreadFactory(shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory()));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
bool apiTestWithThreadFactory(shared_ptr<PlatformThreadFactory> threadFactory)
|
||||
{
|
||||
shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(1);
|
||||
threadManager->threadFactory(threadFactory);
|
||||
|
||||
#if !USE_BOOST_THREAD && !USE_STD_THREAD
|
||||
threadFactory->setPriority(PosixThreadFactory::HIGHEST);
|
||||
|
||||
// verify we cannot change the thread factory to one with the opposite detached setting
|
||||
shared_ptr<PlatformThreadFactory> threadFactory2
|
||||
= shared_ptr<PosixThreadFactory>(new PlatformThreadFactory(
|
||||
PosixThreadFactory::ROUND_ROBIN,
|
||||
PosixThreadFactory::NORMAL,
|
||||
1,
|
||||
!threadFactory->isDetached()));
|
||||
try {
|
||||
threadManager->threadFactory(threadFactory2);
|
||||
// if the call succeeded we changed the thread factory to one that had the opposite setting for "isDetached()".
|
||||
// this is bad, because the thread manager checks with the thread factory to see if it should join threads
|
||||
// as they are leaving - so the detached status of new threads cannot change while there are existing threads.
|
||||
std::cerr << "\t\t\tShould not be able to change thread factory detached disposition" << std::endl;
|
||||
return false;
|
||||
}
|
||||
catch (InvalidArgumentException& ex) {
|
||||
/* expected */
|
||||
}
|
||||
#endif
|
||||
|
||||
std::cout << "\t\t\t\tstarting.. " << std::endl;
|
||||
|
||||
threadManager->start();
|
||||
threadManager->setExpireCallback(expiredNotifier); // apache::thrift::stdcxx::bind(&ThreadManagerTests::expiredNotifier, this));
|
||||
|
||||
#define EXPECT(FUNC, COUNT) { size_t c = FUNC; if (c != COUNT) { std::cerr << "expected " #FUNC" to be " #COUNT ", but was " << c << std::endl; return false; } }
|
||||
|
||||
EXPECT(threadManager->workerCount(), 1);
|
||||
EXPECT(threadManager->idleWorkerCount(), 1);
|
||||
EXPECT(threadManager->pendingTaskCount(), 0);
|
||||
|
||||
std::cout << "\t\t\t\tadd 2nd worker.. " << std::endl;
|
||||
|
||||
threadManager->addWorker();
|
||||
|
||||
EXPECT(threadManager->workerCount(), 2);
|
||||
EXPECT(threadManager->idleWorkerCount(), 2);
|
||||
EXPECT(threadManager->pendingTaskCount(), 0);
|
||||
|
||||
std::cout << "\t\t\t\tremove 2nd worker.. " << std::endl;
|
||||
|
||||
threadManager->removeWorker();
|
||||
|
||||
EXPECT(threadManager->workerCount(), 1);
|
||||
EXPECT(threadManager->idleWorkerCount(), 1);
|
||||
EXPECT(threadManager->pendingTaskCount(), 0);
|
||||
|
||||
std::cout << "\t\t\t\tremove 1st worker.. " << std::endl;
|
||||
|
||||
threadManager->removeWorker();
|
||||
|
||||
EXPECT(threadManager->workerCount(), 0);
|
||||
EXPECT(threadManager->idleWorkerCount(), 0);
|
||||
EXPECT(threadManager->pendingTaskCount(), 0);
|
||||
|
||||
std::cout << "\t\t\t\tadd blocking task.. " << std::endl;
|
||||
|
||||
// We're going to throw a blocking task into the mix
|
||||
Monitor entryMonitor; // signaled when task is running
|
||||
Monitor blockMonitor; // to be signaled to unblock the task
|
||||
bool blocked(true); // set to false before notifying
|
||||
Monitor doneMonitor; // signaled when count reaches zero
|
||||
size_t activeCount = 1;
|
||||
shared_ptr<ThreadManagerTests::BlockTask> blockingTask(
|
||||
new ThreadManagerTests::BlockTask(entryMonitor, blockMonitor, blocked, doneMonitor, activeCount));
|
||||
threadManager->add(blockingTask);
|
||||
|
||||
EXPECT(threadManager->workerCount(), 0);
|
||||
EXPECT(threadManager->idleWorkerCount(), 0);
|
||||
EXPECT(threadManager->pendingTaskCount(), 1);
|
||||
|
||||
std::cout << "\t\t\t\tadd other task.. " << std::endl;
|
||||
|
||||
shared_ptr<ThreadManagerTests::Task> otherTask(
|
||||
new ThreadManagerTests::Task(doneMonitor, activeCount, 0));
|
||||
|
||||
threadManager->add(otherTask);
|
||||
|
||||
EXPECT(threadManager->workerCount(), 0);
|
||||
EXPECT(threadManager->idleWorkerCount(), 0);
|
||||
EXPECT(threadManager->pendingTaskCount(), 2);
|
||||
|
||||
std::cout << "\t\t\t\tremove blocking task specifically.. " << std::endl;
|
||||
|
||||
threadManager->remove(blockingTask);
|
||||
|
||||
EXPECT(threadManager->workerCount(), 0);
|
||||
EXPECT(threadManager->idleWorkerCount(), 0);
|
||||
EXPECT(threadManager->pendingTaskCount(), 1);
|
||||
|
||||
std::cout << "\t\t\t\tremove next pending task.." << std::endl;
|
||||
|
||||
shared_ptr<Runnable> nextTask = threadManager->removeNextPending();
|
||||
if (nextTask != otherTask) {
|
||||
std::cerr << "\t\t\t\t\texpected removeNextPending to return otherTask" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
EXPECT(threadManager->workerCount(), 0);
|
||||
EXPECT(threadManager->idleWorkerCount(), 0);
|
||||
EXPECT(threadManager->pendingTaskCount(), 0);
|
||||
|
||||
std::cout << "\t\t\t\tremove next pending task (none left).." << std::endl;
|
||||
|
||||
nextTask = threadManager->removeNextPending();
|
||||
if (nextTask) {
|
||||
std::cerr << "\t\t\t\t\texpected removeNextPending to return an empty Runnable" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << "\t\t\t\tadd 2 expired tasks and 1 not.." << std::endl;
|
||||
|
||||
shared_ptr<ThreadManagerTests::Task> expiredTask(
|
||||
new ThreadManagerTests::Task(doneMonitor, activeCount, 0));
|
||||
|
||||
threadManager->add(expiredTask, 0, 1);
|
||||
threadManager->add(blockingTask); // add one that hasn't expired to make sure it gets skipped
|
||||
threadManager->add(expiredTask, 0, 1); // add a second expired to ensure removeExpiredTasks removes both
|
||||
|
||||
sleep_(50); // make sure enough time elapses for it to expire - the shortest expiration time is 1 millisecond
|
||||
|
||||
EXPECT(threadManager->workerCount(), 0);
|
||||
EXPECT(threadManager->idleWorkerCount(), 0);
|
||||
EXPECT(threadManager->pendingTaskCount(), 3);
|
||||
EXPECT(threadManager->expiredTaskCount(), 0);
|
||||
|
||||
std::cout << "\t\t\t\tremove expired tasks.." << std::endl;
|
||||
|
||||
if (!m_expired.empty()) {
|
||||
std::cerr << "\t\t\t\t\texpected m_expired to be empty" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
threadManager->removeExpiredTasks();
|
||||
|
||||
if (m_expired.size() != 2) {
|
||||
std::cerr << "\t\t\t\t\texpected m_expired to be set" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_expired.front() != expiredTask) {
|
||||
std::cerr << "\t\t\t\t\texpected m_expired[0] to be the expired task" << std::endl;
|
||||
return false;
|
||||
}
|
||||
m_expired.pop_front();
|
||||
|
||||
if (m_expired.front() != expiredTask) {
|
||||
std::cerr << "\t\t\t\t\texpected m_expired[1] to be the expired task" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_expired.clear();
|
||||
|
||||
threadManager->remove(blockingTask);
|
||||
|
||||
EXPECT(threadManager->workerCount(), 0);
|
||||
EXPECT(threadManager->idleWorkerCount(), 0);
|
||||
EXPECT(threadManager->pendingTaskCount(), 0);
|
||||
EXPECT(threadManager->expiredTaskCount(), 2);
|
||||
|
||||
std::cout << "\t\t\t\tadd expired task (again).." << std::endl;
|
||||
|
||||
threadManager->add(expiredTask, 0, 1); // expires in 1ms
|
||||
sleep_(50); // make sure enough time elapses for it to expire - the shortest expiration time is 1ms
|
||||
|
||||
std::cout << "\t\t\t\tadd worker to consume expired task.." << std::endl;
|
||||
|
||||
threadManager->addWorker();
|
||||
sleep_(100); // make sure it has time to spin up and expire the task
|
||||
|
||||
if (m_expired.empty()) {
|
||||
std::cerr << "\t\t\t\t\texpected m_expired to be set" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_expired.front() != expiredTask) {
|
||||
std::cerr << "\t\t\t\t\texpected m_expired to be the expired task" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_expired.clear();
|
||||
|
||||
EXPECT(threadManager->workerCount(), 1);
|
||||
EXPECT(threadManager->idleWorkerCount(), 1);
|
||||
EXPECT(threadManager->pendingTaskCount(), 0);
|
||||
EXPECT(threadManager->expiredTaskCount(), 3);
|
||||
|
||||
std::cout << "\t\t\t\ttry to remove too many workers" << std::endl;
|
||||
try {
|
||||
threadManager->removeWorker(2);
|
||||
std::cerr << "\t\t\t\t\texpected InvalidArgumentException" << std::endl;
|
||||
return false;
|
||||
} catch (const InvalidArgumentException&) {
|
||||
/* expected */
|
||||
}
|
||||
|
||||
std::cout << "\t\t\t\tremove worker.. " << std::endl;
|
||||
|
||||
threadManager->removeWorker();
|
||||
|
||||
EXPECT(threadManager->workerCount(), 0);
|
||||
EXPECT(threadManager->idleWorkerCount(), 0);
|
||||
EXPECT(threadManager->pendingTaskCount(), 0);
|
||||
EXPECT(threadManager->expiredTaskCount(), 3);
|
||||
|
||||
std::cout << "\t\t\t\tadd blocking task.. " << std::endl;
|
||||
|
||||
threadManager->add(blockingTask);
|
||||
|
||||
EXPECT(threadManager->workerCount(), 0);
|
||||
EXPECT(threadManager->idleWorkerCount(), 0);
|
||||
EXPECT(threadManager->pendingTaskCount(), 1);
|
||||
|
||||
std::cout << "\t\t\t\tadd worker.. " << std::endl;
|
||||
|
||||
threadManager->addWorker();
|
||||
{
|
||||
Synchronized s(entryMonitor);
|
||||
while (!blockingTask->_entered) {
|
||||
entryMonitor.wait();
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT(threadManager->workerCount(), 1);
|
||||
EXPECT(threadManager->idleWorkerCount(), 0);
|
||||
EXPECT(threadManager->pendingTaskCount(), 0);
|
||||
|
||||
std::cout << "\t\t\t\tunblock task and remove worker.. " << std::endl;
|
||||
|
||||
{
|
||||
Synchronized s(blockMonitor);
|
||||
blocked = false;
|
||||
blockMonitor.notifyAll();
|
||||
}
|
||||
threadManager->removeWorker();
|
||||
|
||||
EXPECT(threadManager->workerCount(), 0);
|
||||
EXPECT(threadManager->idleWorkerCount(), 0);
|
||||
EXPECT(threadManager->pendingTaskCount(), 0);
|
||||
|
||||
std::cout << "\t\t\t\tcleanup.. " << std::endl;
|
||||
|
||||
blockingTask.reset();
|
||||
threadManager.reset();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
||||
|
||||
using namespace apache::thrift::concurrency::test;
|
137
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/TimerManagerTests.h
generated
vendored
Normal file
137
vendor/git.apache.org/thrift.git/lib/cpp/test/concurrency/TimerManagerTests.h
generated
vendored
Normal file
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 <thrift/concurrency/TimerManager.h>
|
||||
#include <thrift/concurrency/PlatformThreadFactory.h>
|
||||
#include <thrift/concurrency/Monitor.h>
|
||||
#include <thrift/concurrency/Util.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace concurrency {
|
||||
namespace test {
|
||||
|
||||
using namespace apache::thrift::concurrency;
|
||||
|
||||
class TimerManagerTests {
|
||||
|
||||
public:
|
||||
class Task : public Runnable {
|
||||
public:
|
||||
Task(Monitor& monitor, int64_t timeout)
|
||||
: _timeout(timeout),
|
||||
_startTime(Util::currentTime()),
|
||||
_endTime(0),
|
||||
_monitor(monitor),
|
||||
_success(false),
|
||||
_done(false) {}
|
||||
|
||||
~Task() { std::cerr << this << std::endl; }
|
||||
|
||||
void run() {
|
||||
|
||||
_endTime = Util::currentTime();
|
||||
_success = (_endTime - _startTime) >= _timeout;
|
||||
|
||||
{
|
||||
Synchronized s(_monitor);
|
||||
_done = true;
|
||||
_monitor.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
int64_t _timeout;
|
||||
int64_t _startTime;
|
||||
int64_t _endTime;
|
||||
Monitor& _monitor;
|
||||
bool _success;
|
||||
bool _done;
|
||||
};
|
||||
|
||||
/**
|
||||
* This test creates two tasks and waits for the first to expire within 10%
|
||||
* of the expected expiration time. It then verifies that the timer manager
|
||||
* properly clean up itself and the remaining orphaned timeout task when the
|
||||
* manager goes out of scope and its destructor is called.
|
||||
*/
|
||||
bool test00(int64_t timeout = 1000LL) {
|
||||
|
||||
shared_ptr<TimerManagerTests::Task> orphanTask
|
||||
= shared_ptr<TimerManagerTests::Task>(new TimerManagerTests::Task(_monitor, 10 * timeout));
|
||||
|
||||
{
|
||||
|
||||
TimerManager timerManager;
|
||||
|
||||
timerManager.threadFactory(shared_ptr<PlatformThreadFactory>(new PlatformThreadFactory()));
|
||||
|
||||
timerManager.start();
|
||||
|
||||
assert(timerManager.state() == TimerManager::STARTED);
|
||||
|
||||
// Don't create task yet, because its constructor sets the expected completion time, and we
|
||||
// need to delay between inserting the two tasks into the run queue.
|
||||
shared_ptr<TimerManagerTests::Task> task;
|
||||
|
||||
{
|
||||
Synchronized s(_monitor);
|
||||
|
||||
timerManager.add(orphanTask, 10 * timeout);
|
||||
|
||||
try {
|
||||
// Wait for 1 second in order to give timerManager a chance to start sleeping in response
|
||||
// to adding orphanTask. We need to do this so we can verify that adding the second task
|
||||
// kicks the dispatcher out of the current wait and starts the new 1 second wait.
|
||||
_monitor.wait(1000);
|
||||
assert(
|
||||
0 == "ERROR: This wait should time out. TimerManager dispatcher may have a problem.");
|
||||
} catch (TimedOutException&) {
|
||||
}
|
||||
|
||||
task.reset(new TimerManagerTests::Task(_monitor, timeout));
|
||||
|
||||
timerManager.add(task, timeout);
|
||||
|
||||
_monitor.wait();
|
||||
}
|
||||
|
||||
assert(task->_done);
|
||||
|
||||
std::cout << "\t\t\t" << (task->_success ? "Success" : "Failure") << "!" << std::endl;
|
||||
}
|
||||
|
||||
// timerManager.stop(); This is where it happens via destructor
|
||||
|
||||
assert(!orphanTask->_done);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
friend class TestTask;
|
||||
|
||||
Monitor _monitor;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::concurrency
|
22
vendor/git.apache.org/thrift.git/lib/cpp/test/link/LinkTest.cpp
generated
vendored
Normal file
22
vendor/git.apache.org/thrift.git/lib/cpp/test/link/LinkTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
int main(int, char**) {
|
||||
return 0;
|
||||
}
|
26
vendor/git.apache.org/thrift.git/lib/cpp/test/link/TemplatedService1.cpp
generated
vendored
Normal file
26
vendor/git.apache.org/thrift.git/lib/cpp/test/link/TemplatedService1.cpp
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is a part of a link test that makes sure generated
|
||||
* templated service headers can be included from multiple
|
||||
* implementation files.
|
||||
*/
|
||||
|
||||
#include "gen-cpp/ParentService.h"
|
26
vendor/git.apache.org/thrift.git/lib/cpp/test/link/TemplatedService2.cpp
generated
vendored
Normal file
26
vendor/git.apache.org/thrift.git/lib/cpp/test/link/TemplatedService2.cpp
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is a part of a link test that makes sure generated
|
||||
* templated service headers can be included from multiple
|
||||
* implementation files.
|
||||
*/
|
||||
|
||||
#include "gen-cpp/ParentService.h"
|
136
vendor/git.apache.org/thrift.git/lib/cpp/test/processor/EventLog.cpp
generated
vendored
Normal file
136
vendor/git.apache.org/thrift.git/lib/cpp/test/processor/EventLog.cpp
generated
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 "EventLog.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace apache::thrift::concurrency;
|
||||
|
||||
namespace {
|
||||
|
||||
// Define environment variable DEBUG_EVENTLOG to enable debug logging
|
||||
// ex: $ DEBUG_EVENTLOG=1 processor_test
|
||||
static const char * DEBUG_EVENTLOG = getenv("DEBUG_EVENTLOG");
|
||||
|
||||
void debug(const char* fmt, ...) {
|
||||
if (DEBUG_EVENTLOG) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace test {
|
||||
|
||||
uint32_t EventLog::nextId_ = 0;
|
||||
|
||||
#define EVENT_TYPE(value) EventType EventLog::value = #value
|
||||
EVENT_TYPE(ET_LOG_END);
|
||||
EVENT_TYPE(ET_CONN_CREATED);
|
||||
EVENT_TYPE(ET_CONN_DESTROYED);
|
||||
EVENT_TYPE(ET_CALL_STARTED);
|
||||
EVENT_TYPE(ET_CALL_FINISHED);
|
||||
EVENT_TYPE(ET_PROCESS);
|
||||
EVENT_TYPE(ET_PRE_READ);
|
||||
EVENT_TYPE(ET_POST_READ);
|
||||
EVENT_TYPE(ET_PRE_WRITE);
|
||||
EVENT_TYPE(ET_POST_WRITE);
|
||||
EVENT_TYPE(ET_ASYNC_COMPLETE);
|
||||
EVENT_TYPE(ET_HANDLER_ERROR);
|
||||
|
||||
EVENT_TYPE(ET_CALL_INCREMENT_GENERATION);
|
||||
EVENT_TYPE(ET_CALL_GET_GENERATION);
|
||||
EVENT_TYPE(ET_CALL_ADD_STRING);
|
||||
EVENT_TYPE(ET_CALL_GET_STRINGS);
|
||||
EVENT_TYPE(ET_CALL_GET_DATA_WAIT);
|
||||
EVENT_TYPE(ET_CALL_ONEWAY_WAIT);
|
||||
EVENT_TYPE(ET_CALL_EXCEPTION_WAIT);
|
||||
EVENT_TYPE(ET_CALL_UNEXPECTED_EXCEPTION_WAIT);
|
||||
EVENT_TYPE(ET_CALL_SET_VALUE);
|
||||
EVENT_TYPE(ET_CALL_GET_VALUE);
|
||||
EVENT_TYPE(ET_WAIT_RETURN);
|
||||
|
||||
EventLog::EventLog() {
|
||||
id_ = nextId_++;
|
||||
debug("New log: %d", id_);
|
||||
}
|
||||
|
||||
void EventLog::append(EventType type,
|
||||
uint32_t connectionId,
|
||||
uint32_t callId,
|
||||
const string& message) {
|
||||
Synchronized s(monitor_);
|
||||
debug("%d <-- %u, %u, %s \"%s\"", id_, connectionId, callId, type, message.c_str());
|
||||
|
||||
Event e(type, connectionId, callId, message);
|
||||
events_.push_back(e);
|
||||
|
||||
monitor_.notify();
|
||||
}
|
||||
|
||||
Event EventLog::waitForEvent(int64_t timeout) {
|
||||
Synchronized s(monitor_);
|
||||
|
||||
try {
|
||||
while (events_.empty()) {
|
||||
monitor_.wait(timeout);
|
||||
}
|
||||
} catch (TimedOutException ex) {
|
||||
return Event(ET_LOG_END, 0, 0, "");
|
||||
}
|
||||
|
||||
Event event = events_.front();
|
||||
events_.pop_front();
|
||||
return event;
|
||||
}
|
||||
|
||||
Event EventLog::waitForConnEvent(uint32_t connId, int64_t timeout) {
|
||||
Synchronized s(monitor_);
|
||||
|
||||
EventList::iterator it = events_.begin();
|
||||
while (true) {
|
||||
try {
|
||||
// TODO: it would be nicer to honor timeout for the duration of this
|
||||
// call, rather than restarting it for each call to wait(). It shouldn't
|
||||
// be a big problem in practice, though.
|
||||
while (it == events_.end()) {
|
||||
monitor_.wait(timeout);
|
||||
}
|
||||
} catch (TimedOutException ex) {
|
||||
return Event(ET_LOG_END, 0, 0, "");
|
||||
}
|
||||
|
||||
if (it->connectionId == connId) {
|
||||
Event event = *it;
|
||||
events_.erase(it);
|
||||
return event;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::test
|
95
vendor/git.apache.org/thrift.git/lib/cpp/test/processor/EventLog.h
generated
vendored
Normal file
95
vendor/git.apache.org/thrift.git/lib/cpp/test/processor/EventLog.h
generated
vendored
Normal file
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 _THRIFT_TEST_EVENTLOG_H_
|
||||
#define _THRIFT_TEST_EVENTLOG_H_ 1
|
||||
|
||||
#include <thrift/concurrency/Monitor.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace test {
|
||||
|
||||
// Initially I made EventType an enum, but using char* results
|
||||
// in much more readable error messages when there is a mismatch.
|
||||
// It also lets users of EventLog easily define their own new types.
|
||||
// Comparing the literal pointer values should be safe, barring any strange
|
||||
// linking setup that results in duplicate symbols.
|
||||
typedef const char* EventType;
|
||||
|
||||
struct Event {
|
||||
Event(EventType type, uint32_t connectionId, uint32_t callId, const std::string& message)
|
||||
: type(type), connectionId(connectionId), callId(callId), message(message) {}
|
||||
|
||||
EventType type;
|
||||
uint32_t connectionId;
|
||||
uint32_t callId;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
class EventLog {
|
||||
public:
|
||||
static EventType ET_LOG_END;
|
||||
static EventType ET_CONN_CREATED;
|
||||
static EventType ET_CONN_DESTROYED;
|
||||
static EventType ET_CALL_STARTED;
|
||||
static EventType ET_CALL_FINISHED;
|
||||
static EventType ET_PROCESS;
|
||||
static EventType ET_PRE_READ;
|
||||
static EventType ET_POST_READ;
|
||||
static EventType ET_PRE_WRITE;
|
||||
static EventType ET_POST_WRITE;
|
||||
static EventType ET_ASYNC_COMPLETE;
|
||||
static EventType ET_HANDLER_ERROR;
|
||||
|
||||
static EventType ET_CALL_INCREMENT_GENERATION;
|
||||
static EventType ET_CALL_GET_GENERATION;
|
||||
static EventType ET_CALL_ADD_STRING;
|
||||
static EventType ET_CALL_GET_STRINGS;
|
||||
static EventType ET_CALL_GET_DATA_WAIT;
|
||||
static EventType ET_CALL_ONEWAY_WAIT;
|
||||
static EventType ET_CALL_UNEXPECTED_EXCEPTION_WAIT;
|
||||
static EventType ET_CALL_EXCEPTION_WAIT;
|
||||
static EventType ET_WAIT_RETURN;
|
||||
static EventType ET_CALL_SET_VALUE;
|
||||
static EventType ET_CALL_GET_VALUE;
|
||||
|
||||
EventLog();
|
||||
|
||||
void append(EventType type,
|
||||
uint32_t connectionId,
|
||||
uint32_t callId,
|
||||
const std::string& message = "");
|
||||
|
||||
Event waitForEvent(int64_t timeout = 500);
|
||||
Event waitForConnEvent(uint32_t connId, int64_t timeout = 500);
|
||||
|
||||
protected:
|
||||
typedef std::list<Event> EventList;
|
||||
|
||||
concurrency::Monitor monitor_;
|
||||
EventList events_;
|
||||
uint32_t id_;
|
||||
|
||||
static uint32_t nextId_;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // apache::thrift::test
|
||||
|
||||
#endif // _THRIFT_TEST_EVENTLOG_H_
|
338
vendor/git.apache.org/thrift.git/lib/cpp/test/processor/Handlers.h
generated
vendored
Normal file
338
vendor/git.apache.org/thrift.git/lib/cpp/test/processor/Handlers.h
generated
vendored
Normal file
|
@ -0,0 +1,338 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 _THRIFT_PROCESSOR_TEST_HANDLERS_H_
|
||||
#define _THRIFT_PROCESSOR_TEST_HANDLERS_H_ 1
|
||||
|
||||
#include "EventLog.h"
|
||||
#include "gen-cpp/ParentService.h"
|
||||
#include "gen-cpp/ChildService.h"
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace test {
|
||||
|
||||
class ParentHandler : virtual public ParentServiceIf {
|
||||
public:
|
||||
ParentHandler(const boost::shared_ptr<EventLog>& log)
|
||||
: triggerMonitor(&mutex_), generation_(0), wait_(false), log_(log) {}
|
||||
|
||||
int32_t incrementGeneration() {
|
||||
concurrency::Guard g(mutex_);
|
||||
log_->append(EventLog::ET_CALL_INCREMENT_GENERATION, 0, 0);
|
||||
return ++generation_;
|
||||
}
|
||||
|
||||
int32_t getGeneration() {
|
||||
concurrency::Guard g(mutex_);
|
||||
log_->append(EventLog::ET_CALL_GET_GENERATION, 0, 0);
|
||||
return generation_;
|
||||
}
|
||||
|
||||
void addString(const std::string& s) {
|
||||
concurrency::Guard g(mutex_);
|
||||
log_->append(EventLog::ET_CALL_ADD_STRING, 0, 0);
|
||||
strings_.push_back(s);
|
||||
}
|
||||
|
||||
void getStrings(std::vector<std::string>& _return) {
|
||||
concurrency::Guard g(mutex_);
|
||||
log_->append(EventLog::ET_CALL_GET_STRINGS, 0, 0);
|
||||
_return = strings_;
|
||||
}
|
||||
|
||||
void getDataWait(std::string& _return, const int32_t length) {
|
||||
concurrency::Guard g(mutex_);
|
||||
log_->append(EventLog::ET_CALL_GET_DATA_WAIT, 0, 0);
|
||||
|
||||
blockUntilTriggered();
|
||||
|
||||
_return.append(length, 'a');
|
||||
}
|
||||
|
||||
void onewayWait() {
|
||||
concurrency::Guard g(mutex_);
|
||||
log_->append(EventLog::ET_CALL_ONEWAY_WAIT, 0, 0);
|
||||
|
||||
blockUntilTriggered();
|
||||
}
|
||||
|
||||
void exceptionWait(const std::string& message) {
|
||||
concurrency::Guard g(mutex_);
|
||||
log_->append(EventLog::ET_CALL_EXCEPTION_WAIT, 0, 0);
|
||||
|
||||
blockUntilTriggered();
|
||||
|
||||
MyError e;
|
||||
e.message = message;
|
||||
throw e;
|
||||
}
|
||||
|
||||
void unexpectedExceptionWait(const std::string& message) {
|
||||
concurrency::Guard g(mutex_);
|
||||
log_->append(EventLog::ET_CALL_UNEXPECTED_EXCEPTION_WAIT, 0, 0);
|
||||
|
||||
blockUntilTriggered();
|
||||
|
||||
MyError e;
|
||||
e.message = message;
|
||||
throw e;
|
||||
}
|
||||
|
||||
/**
|
||||
* After prepareTriggeredCall() is invoked, calls to any of the *Wait()
|
||||
* functions won't return until triggerPendingCalls() is invoked
|
||||
*
|
||||
* This has to be a separate function invoked by the main test thread
|
||||
* in order to to avoid race conditions.
|
||||
*/
|
||||
void prepareTriggeredCall() {
|
||||
concurrency::Guard g(mutex_);
|
||||
wait_ = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wake up all calls waiting in blockUntilTriggered()
|
||||
*/
|
||||
void triggerPendingCalls() {
|
||||
concurrency::Guard g(mutex_);
|
||||
wait_ = false;
|
||||
triggerMonitor.notifyAll();
|
||||
}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* blockUntilTriggered() won't return until triggerPendingCalls() is invoked
|
||||
* in another thread.
|
||||
*
|
||||
* This should only be called when already holding mutex_.
|
||||
*/
|
||||
void blockUntilTriggered() {
|
||||
while (wait_) {
|
||||
triggerMonitor.waitForever();
|
||||
}
|
||||
|
||||
// Log an event when we return
|
||||
log_->append(EventLog::ET_WAIT_RETURN, 0, 0);
|
||||
}
|
||||
|
||||
concurrency::Mutex mutex_;
|
||||
concurrency::Monitor triggerMonitor;
|
||||
int32_t generation_;
|
||||
bool wait_;
|
||||
std::vector<std::string> strings_;
|
||||
boost::shared_ptr<EventLog> log_;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning( push )
|
||||
#pragma warning (disable : 4250 ) //inheriting methods via dominance
|
||||
#endif
|
||||
|
||||
class ChildHandler : public ParentHandler, virtual public ChildServiceIf {
|
||||
public:
|
||||
ChildHandler(const boost::shared_ptr<EventLog>& log) : ParentHandler(log), value_(0) {}
|
||||
|
||||
int32_t setValue(const int32_t value) {
|
||||
concurrency::Guard g(mutex_);
|
||||
log_->append(EventLog::ET_CALL_SET_VALUE, 0, 0);
|
||||
|
||||
int32_t oldValue = value_;
|
||||
value_ = value;
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
int32_t getValue() {
|
||||
concurrency::Guard g(mutex_);
|
||||
log_->append(EventLog::ET_CALL_GET_VALUE, 0, 0);
|
||||
|
||||
return value_;
|
||||
}
|
||||
|
||||
protected:
|
||||
int32_t value_;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
|
||||
struct ConnContext {
|
||||
public:
|
||||
ConnContext(boost::shared_ptr<protocol::TProtocol> in,
|
||||
boost::shared_ptr<protocol::TProtocol> out,
|
||||
uint32_t id)
|
||||
: input(in), output(out), id(id) {}
|
||||
|
||||
boost::shared_ptr<protocol::TProtocol> input;
|
||||
boost::shared_ptr<protocol::TProtocol> output;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
struct CallContext {
|
||||
public:
|
||||
CallContext(ConnContext* context, uint32_t id, const std::string& name)
|
||||
: connContext(context), name(name), id(id) {}
|
||||
|
||||
ConnContext* connContext;
|
||||
std::string name;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
class ServerEventHandler : public server::TServerEventHandler {
|
||||
public:
|
||||
ServerEventHandler(const boost::shared_ptr<EventLog>& log) : nextId_(1), log_(log) {}
|
||||
|
||||
virtual void preServe() {}
|
||||
|
||||
virtual void* createContext(boost::shared_ptr<protocol::TProtocol> input,
|
||||
boost::shared_ptr<protocol::TProtocol> output) {
|
||||
ConnContext* context = new ConnContext(input, output, nextId_);
|
||||
++nextId_;
|
||||
log_->append(EventLog::ET_CONN_CREATED, context->id, 0);
|
||||
return context;
|
||||
}
|
||||
|
||||
virtual void deleteContext(void* serverContext,
|
||||
boost::shared_ptr<protocol::TProtocol> input,
|
||||
boost::shared_ptr<protocol::TProtocol> output) {
|
||||
ConnContext* context = reinterpret_cast<ConnContext*>(serverContext);
|
||||
|
||||
if (input != context->input) {
|
||||
abort();
|
||||
}
|
||||
if (output != context->output) {
|
||||
abort();
|
||||
}
|
||||
|
||||
log_->append(EventLog::ET_CONN_DESTROYED, context->id, 0);
|
||||
|
||||
delete context;
|
||||
}
|
||||
|
||||
virtual void processContext(void* serverContext,
|
||||
boost::shared_ptr<transport::TTransport> transport) {
|
||||
// TODO: We currently don't test the behavior of the processContext()
|
||||
// calls. The various server implementations call processContext() at
|
||||
// slightly different times, and it is too annoying to try and account for
|
||||
// their various differences.
|
||||
//
|
||||
// TThreadedServer, TThreadPoolServer, and TSimpleServer usually wait until
|
||||
// they see the first byte of a request before calling processContext().
|
||||
// However, they don't wait for the first byte of the very first request,
|
||||
// and instead immediately call processContext() before any data is
|
||||
// received.
|
||||
//
|
||||
// TNonblockingServer always waits until receiving the full request before
|
||||
// calling processContext().
|
||||
#if 0
|
||||
ConnContext* context = reinterpret_cast<ConnContext*>(serverContext);
|
||||
log_->append(EventLog::ET_PROCESS, context->id, 0);
|
||||
#else
|
||||
THRIFT_UNUSED_VARIABLE(serverContext);
|
||||
THRIFT_UNUSED_VARIABLE(transport);
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
uint32_t nextId_;
|
||||
boost::shared_ptr<EventLog> log_;
|
||||
};
|
||||
|
||||
class ProcessorEventHandler : public TProcessorEventHandler {
|
||||
public:
|
||||
ProcessorEventHandler(const boost::shared_ptr<EventLog>& log) : nextId_(1), log_(log) {}
|
||||
|
||||
void* getContext(const char* fnName, void* serverContext) {
|
||||
ConnContext* connContext = reinterpret_cast<ConnContext*>(serverContext);
|
||||
|
||||
CallContext* context = new CallContext(connContext, nextId_, fnName);
|
||||
++nextId_;
|
||||
|
||||
log_->append(EventLog::ET_CALL_STARTED, connContext->id, context->id, fnName);
|
||||
return context;
|
||||
}
|
||||
|
||||
void freeContext(void* ctx, const char* fnName) {
|
||||
CallContext* context = reinterpret_cast<CallContext*>(ctx);
|
||||
checkName(context, fnName);
|
||||
log_->append(EventLog::ET_CALL_FINISHED, context->connContext->id, context->id, fnName);
|
||||
delete context;
|
||||
}
|
||||
|
||||
void preRead(void* ctx, const char* fnName) {
|
||||
CallContext* context = reinterpret_cast<CallContext*>(ctx);
|
||||
checkName(context, fnName);
|
||||
log_->append(EventLog::ET_PRE_READ, context->connContext->id, context->id, fnName);
|
||||
}
|
||||
|
||||
void postRead(void* ctx, const char* fnName, uint32_t bytes) {
|
||||
THRIFT_UNUSED_VARIABLE(bytes);
|
||||
CallContext* context = reinterpret_cast<CallContext*>(ctx);
|
||||
checkName(context, fnName);
|
||||
log_->append(EventLog::ET_POST_READ, context->connContext->id, context->id, fnName);
|
||||
}
|
||||
|
||||
void preWrite(void* ctx, const char* fnName) {
|
||||
CallContext* context = reinterpret_cast<CallContext*>(ctx);
|
||||
checkName(context, fnName);
|
||||
log_->append(EventLog::ET_PRE_WRITE, context->connContext->id, context->id, fnName);
|
||||
}
|
||||
|
||||
void postWrite(void* ctx, const char* fnName, uint32_t bytes) {
|
||||
THRIFT_UNUSED_VARIABLE(bytes);
|
||||
CallContext* context = reinterpret_cast<CallContext*>(ctx);
|
||||
checkName(context, fnName);
|
||||
log_->append(EventLog::ET_POST_WRITE, context->connContext->id, context->id, fnName);
|
||||
}
|
||||
|
||||
void asyncComplete(void* ctx, const char* fnName) {
|
||||
CallContext* context = reinterpret_cast<CallContext*>(ctx);
|
||||
checkName(context, fnName);
|
||||
log_->append(EventLog::ET_ASYNC_COMPLETE, context->connContext->id, context->id, fnName);
|
||||
}
|
||||
|
||||
void handlerError(void* ctx, const char* fnName) {
|
||||
CallContext* context = reinterpret_cast<CallContext*>(ctx);
|
||||
checkName(context, fnName);
|
||||
log_->append(EventLog::ET_HANDLER_ERROR, context->connContext->id, context->id, fnName);
|
||||
}
|
||||
|
||||
protected:
|
||||
void checkName(const CallContext* context, const char* fnName) {
|
||||
// Note: we can't use BOOST_CHECK_EQUAL here, since the handler runs in a
|
||||
// different thread from the test functions. Just abort if the names are
|
||||
// different
|
||||
if (context->name != fnName) {
|
||||
fprintf(stderr,
|
||||
"call context name mismatch: \"%s\" != \"%s\"\n",
|
||||
context->name.c_str(),
|
||||
fnName);
|
||||
fflush(stderr);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t nextId_;
|
||||
boost::shared_ptr<EventLog> log_;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // apache::thrift::test
|
||||
|
||||
#endif // _THRIFT_PROCESSOR_TEST_HANDLERS_H_
|
927
vendor/git.apache.org/thrift.git/lib/cpp/test/processor/ProcessorTest.cpp
generated
vendored
Normal file
927
vendor/git.apache.org/thrift.git/lib/cpp/test/processor/ProcessorTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,927 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains tests that ensure TProcessorEventHandler and
|
||||
* TServerEventHandler are invoked properly by the various server
|
||||
* implementations.
|
||||
*/
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <thrift/concurrency/PlatformThreadFactory.h>
|
||||
#include <thrift/concurrency/Monitor.h>
|
||||
#include <thrift/protocol/TBinaryProtocol.h>
|
||||
#include <thrift/server/TThreadedServer.h>
|
||||
#include <thrift/server/TThreadPoolServer.h>
|
||||
#include <thrift/server/TNonblockingServer.h>
|
||||
#include <thrift/server/TSimpleServer.h>
|
||||
#include <thrift/transport/TSocket.h>
|
||||
|
||||
#include "EventLog.h"
|
||||
#include "ServerThread.h"
|
||||
#include "Handlers.h"
|
||||
#include "gen-cpp/ChildService.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace boost;
|
||||
using namespace apache::thrift;
|
||||
using namespace apache::thrift::concurrency;
|
||||
using namespace apache::thrift::protocol;
|
||||
using namespace apache::thrift::server;
|
||||
using namespace apache::thrift::transport;
|
||||
|
||||
using namespace apache::thrift::test;
|
||||
|
||||
/*
|
||||
* Traits classes that encapsulate how to create various types of servers.
|
||||
*/
|
||||
|
||||
class TSimpleServerTraits {
|
||||
public:
|
||||
typedef TSimpleServer ServerType;
|
||||
|
||||
boost::shared_ptr<TSimpleServer> createServer(
|
||||
const boost::shared_ptr<TProcessor>& processor,
|
||||
uint16_t port,
|
||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory) {
|
||||
boost::shared_ptr<TServerSocket> socket(new TServerSocket(port));
|
||||
return boost::shared_ptr<TSimpleServer>(
|
||||
new TSimpleServer(processor, socket, transportFactory, protocolFactory));
|
||||
}
|
||||
};
|
||||
|
||||
class TThreadedServerTraits {
|
||||
public:
|
||||
typedef TThreadedServer ServerType;
|
||||
|
||||
boost::shared_ptr<TThreadedServer> createServer(
|
||||
const boost::shared_ptr<TProcessor>& processor,
|
||||
uint16_t port,
|
||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory) {
|
||||
boost::shared_ptr<TServerSocket> socket(new TServerSocket(port));
|
||||
return boost::shared_ptr<TThreadedServer>(
|
||||
new TThreadedServer(processor, socket, transportFactory, protocolFactory));
|
||||
}
|
||||
};
|
||||
|
||||
class TThreadPoolServerTraits {
|
||||
public:
|
||||
typedef TThreadPoolServer ServerType;
|
||||
|
||||
boost::shared_ptr<TThreadPoolServer> createServer(
|
||||
const boost::shared_ptr<TProcessor>& processor,
|
||||
uint16_t port,
|
||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory) {
|
||||
boost::shared_ptr<TServerSocket> socket(new TServerSocket(port));
|
||||
|
||||
boost::shared_ptr<PlatformThreadFactory> threadFactory(new PlatformThreadFactory);
|
||||
boost::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(8);
|
||||
threadManager->threadFactory(threadFactory);
|
||||
threadManager->start();
|
||||
|
||||
return boost::shared_ptr<TThreadPoolServer>(
|
||||
new TThreadPoolServer(processor, socket, transportFactory, protocolFactory, threadManager));
|
||||
}
|
||||
};
|
||||
|
||||
class TNonblockingServerTraits {
|
||||
public:
|
||||
typedef TNonblockingServer ServerType;
|
||||
|
||||
boost::shared_ptr<TNonblockingServer> createServer(
|
||||
const boost::shared_ptr<TProcessor>& processor,
|
||||
uint16_t port,
|
||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory) {
|
||||
// TNonblockingServer automatically uses TFramedTransport.
|
||||
// Raise an exception if the supplied transport factory is not a
|
||||
// TFramedTransportFactory
|
||||
TFramedTransportFactory* framedFactory
|
||||
= dynamic_cast<TFramedTransportFactory*>(transportFactory.get());
|
||||
if (framedFactory == NULL) {
|
||||
throw TException("TNonblockingServer must use TFramedTransport");
|
||||
}
|
||||
|
||||
boost::shared_ptr<PlatformThreadFactory> threadFactory(new PlatformThreadFactory);
|
||||
boost::shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(8);
|
||||
threadManager->threadFactory(threadFactory);
|
||||
threadManager->start();
|
||||
|
||||
return boost::shared_ptr<TNonblockingServer>(
|
||||
new TNonblockingServer(processor, protocolFactory, port, threadManager));
|
||||
}
|
||||
};
|
||||
|
||||
class TNonblockingServerNoThreadsTraits {
|
||||
public:
|
||||
typedef TNonblockingServer ServerType;
|
||||
|
||||
boost::shared_ptr<TNonblockingServer> createServer(
|
||||
const boost::shared_ptr<TProcessor>& processor,
|
||||
uint16_t port,
|
||||
const boost::shared_ptr<TTransportFactory>& transportFactory,
|
||||
const boost::shared_ptr<TProtocolFactory>& protocolFactory) {
|
||||
// TNonblockingServer automatically uses TFramedTransport.
|
||||
// Raise an exception if the supplied transport factory is not a
|
||||
// TFramedTransportFactory
|
||||
TFramedTransportFactory* framedFactory
|
||||
= dynamic_cast<TFramedTransportFactory*>(transportFactory.get());
|
||||
if (framedFactory == NULL) {
|
||||
throw TException("TNonblockingServer must use TFramedTransport");
|
||||
}
|
||||
|
||||
// Use a NULL ThreadManager
|
||||
boost::shared_ptr<ThreadManager> threadManager;
|
||||
return boost::shared_ptr<TNonblockingServer>(
|
||||
new TNonblockingServer(processor, protocolFactory, port, threadManager));
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Traits classes for controlling if we instantiate templated or generic
|
||||
* protocol factories, processors, clients, etc.
|
||||
*
|
||||
* The goal is to allow the outer test code to select which server type is
|
||||
* being tested, and whether or not we are testing the templated classes, or
|
||||
* the generic classes.
|
||||
*
|
||||
* Each specific test case can control whether we create a child or parent
|
||||
* server, and whether we use TFramedTransport or TBufferedTransport.
|
||||
*/
|
||||
|
||||
class UntemplatedTraits {
|
||||
public:
|
||||
typedef TBinaryProtocolFactory ProtocolFactory;
|
||||
typedef TBinaryProtocol Protocol;
|
||||
|
||||
typedef ParentServiceProcessor ParentProcessor;
|
||||
typedef ChildServiceProcessor ChildProcessor;
|
||||
typedef ParentServiceClient ParentClient;
|
||||
typedef ChildServiceClient ChildClient;
|
||||
};
|
||||
|
||||
class TemplatedTraits {
|
||||
public:
|
||||
typedef TBinaryProtocolFactoryT<TBufferBase> ProtocolFactory;
|
||||
typedef TBinaryProtocolT<TBufferBase> Protocol;
|
||||
|
||||
typedef ParentServiceProcessorT<Protocol> ParentProcessor;
|
||||
typedef ChildServiceProcessorT<Protocol> ChildProcessor;
|
||||
typedef ParentServiceClientT<Protocol> ParentClient;
|
||||
typedef ChildServiceClientT<Protocol> ChildClient;
|
||||
};
|
||||
|
||||
template <typename TemplateTraits_>
|
||||
class ParentServiceTraits {
|
||||
public:
|
||||
typedef typename TemplateTraits_::ParentProcessor Processor;
|
||||
typedef typename TemplateTraits_::ParentClient Client;
|
||||
typedef ParentHandler Handler;
|
||||
|
||||
typedef typename TemplateTraits_::ProtocolFactory ProtocolFactory;
|
||||
typedef typename TemplateTraits_::Protocol Protocol;
|
||||
};
|
||||
|
||||
template <typename TemplateTraits_>
|
||||
class ChildServiceTraits {
|
||||
public:
|
||||
typedef typename TemplateTraits_::ChildProcessor Processor;
|
||||
typedef typename TemplateTraits_::ChildClient Client;
|
||||
typedef ChildHandler Handler;
|
||||
|
||||
typedef typename TemplateTraits_::ProtocolFactory ProtocolFactory;
|
||||
typedef typename TemplateTraits_::Protocol Protocol;
|
||||
};
|
||||
|
||||
// TODO: It would be nicer if the TTransportFactory types defined a typedef,
|
||||
// to allow us to figure out the exact transport type without having to pass it
|
||||
// in as a separate template parameter here.
|
||||
//
|
||||
// It would also be niec if they used covariant return types. Unfortunately,
|
||||
// since they return shared_ptr instead of raw pointers, covariant return types
|
||||
// won't work.
|
||||
template <typename ServerTraits_,
|
||||
typename ServiceTraits_,
|
||||
typename TransportFactory_ = TFramedTransportFactory,
|
||||
typename Transport_ = TFramedTransport>
|
||||
class ServiceState : public ServerState {
|
||||
public:
|
||||
typedef typename ServiceTraits_::Processor Processor;
|
||||
typedef typename ServiceTraits_::Client Client;
|
||||
typedef typename ServiceTraits_::Handler Handler;
|
||||
|
||||
ServiceState()
|
||||
: port_(0),
|
||||
log_(new EventLog),
|
||||
handler_(new Handler(log_)),
|
||||
processor_(new Processor(handler_)),
|
||||
transportFactory_(new TransportFactory_),
|
||||
protocolFactory_(new typename ServiceTraits_::ProtocolFactory),
|
||||
serverEventHandler_(new ServerEventHandler(log_)),
|
||||
processorEventHandler_(new ProcessorEventHandler(log_)) {
|
||||
processor_->setEventHandler(processorEventHandler_);
|
||||
}
|
||||
|
||||
boost::shared_ptr<TServer> createServer(uint16_t port) {
|
||||
ServerTraits_ serverTraits;
|
||||
return serverTraits.createServer(processor_, port, transportFactory_, protocolFactory_);
|
||||
}
|
||||
|
||||
boost::shared_ptr<TServerEventHandler> getServerEventHandler() { return serverEventHandler_; }
|
||||
|
||||
void bindSuccessful(uint16_t port) { port_ = port; }
|
||||
|
||||
uint16_t getPort() const { return port_; }
|
||||
|
||||
const boost::shared_ptr<EventLog>& getLog() const { return log_; }
|
||||
|
||||
const boost::shared_ptr<Handler>& getHandler() const { return handler_; }
|
||||
|
||||
boost::shared_ptr<Client> createClient() {
|
||||
typedef typename ServiceTraits_::Protocol Protocol;
|
||||
|
||||
boost::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", port_));
|
||||
boost::shared_ptr<Transport_> transport(new Transport_(socket));
|
||||
boost::shared_ptr<Protocol> protocol(new Protocol(transport));
|
||||
transport->open();
|
||||
|
||||
boost::shared_ptr<Client> client(new Client(protocol));
|
||||
return client;
|
||||
}
|
||||
|
||||
private:
|
||||
uint16_t port_;
|
||||
boost::shared_ptr<EventLog> log_;
|
||||
boost::shared_ptr<Handler> handler_;
|
||||
boost::shared_ptr<Processor> processor_;
|
||||
boost::shared_ptr<TTransportFactory> transportFactory_;
|
||||
boost::shared_ptr<TProtocolFactory> protocolFactory_;
|
||||
boost::shared_ptr<TServerEventHandler> serverEventHandler_;
|
||||
boost::shared_ptr<TProcessorEventHandler> processorEventHandler_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check that there are no more events in the log
|
||||
*/
|
||||
void checkNoEvents(const boost::shared_ptr<EventLog>& log) {
|
||||
// Wait for an event with a very short timeout period. We don't expect
|
||||
// anything to be present, so we will normally wait for the full timeout.
|
||||
// On the other hand, a non-zero timeout is nice since it does give a short
|
||||
// window for events to arrive in case there is a problem.
|
||||
Event event = log->waitForEvent(10);
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_LOG_END, event.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for the events that should be logged when a new connection is created.
|
||||
*
|
||||
* Returns the connection ID allocated by the server.
|
||||
*/
|
||||
uint32_t checkNewConnEvents(const boost::shared_ptr<EventLog>& log) {
|
||||
// Check for an ET_CONN_CREATED event
|
||||
Event event = log->waitForEvent(2500);
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_CONN_CREATED, event.type);
|
||||
|
||||
// Some servers call the processContext() hook immediately.
|
||||
// Others (TNonblockingServer) only call it once a full request is received.
|
||||
// We don't check for it yet, to allow either behavior.
|
||||
|
||||
return event.connectionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for the events that should be logged when a connection is closed.
|
||||
*/
|
||||
void checkCloseEvents(const boost::shared_ptr<EventLog>& log, uint32_t connId) {
|
||||
// Check for an ET_CONN_DESTROYED event
|
||||
Event event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_CONN_DESTROYED, event.type);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
|
||||
// Make sure there are no more events
|
||||
checkNoEvents(log);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for the events that should be logged when a call is received
|
||||
* and the handler is invoked.
|
||||
*
|
||||
* It does not check for anything after the handler invocation.
|
||||
*
|
||||
* Returns the call ID allocated by the server.
|
||||
*/
|
||||
uint32_t checkCallHandlerEvents(const boost::shared_ptr<EventLog>& log,
|
||||
uint32_t connId,
|
||||
EventType callType,
|
||||
const string& callName) {
|
||||
// Call started
|
||||
Event event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_CALL_STARTED, event.type);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callName, event.message);
|
||||
uint32_t callId = event.callId;
|
||||
|
||||
// Pre-read
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_PRE_READ, event.type);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callId, event.callId);
|
||||
BOOST_CHECK_EQUAL(callName, event.message);
|
||||
|
||||
// Post-read
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_POST_READ, event.type);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callId, event.callId);
|
||||
BOOST_CHECK_EQUAL(callName, event.message);
|
||||
|
||||
// Handler invocation
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(callType, event.type);
|
||||
// The handler doesn't have any connection or call context,
|
||||
// so the connectionId and callId in this event aren't valid
|
||||
|
||||
return callId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for the events that should be after a handler returns.
|
||||
*/
|
||||
void checkCallPostHandlerEvents(const boost::shared_ptr<EventLog>& log,
|
||||
uint32_t connId,
|
||||
uint32_t callId,
|
||||
const string& callName) {
|
||||
// Pre-write
|
||||
Event event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_PRE_WRITE, event.type);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callId, event.callId);
|
||||
BOOST_CHECK_EQUAL(callName, event.message);
|
||||
|
||||
// Post-write
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_POST_WRITE, event.type);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callId, event.callId);
|
||||
BOOST_CHECK_EQUAL(callName, event.message);
|
||||
|
||||
// Call finished
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_CALL_FINISHED, event.type);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callId, event.callId);
|
||||
BOOST_CHECK_EQUAL(callName, event.message);
|
||||
|
||||
// It is acceptable for servers to call processContext() again immediately
|
||||
// to start waiting on the next request. However, some servers wait before
|
||||
// getting either a partial request or the full request before calling
|
||||
// processContext(). We don't check for the next call to processContext()
|
||||
// yet.
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for the events that should be logged when a call is made.
|
||||
*
|
||||
* This just calls checkCallHandlerEvents() followed by
|
||||
* checkCallPostHandlerEvents().
|
||||
*
|
||||
* Returns the call ID allocated by the server.
|
||||
*/
|
||||
uint32_t checkCallEvents(const boost::shared_ptr<EventLog>& log,
|
||||
uint32_t connId,
|
||||
EventType callType,
|
||||
const string& callName) {
|
||||
uint32_t callId = checkCallHandlerEvents(log, connId, callType, callName);
|
||||
checkCallPostHandlerEvents(log, connId, callId, callName);
|
||||
|
||||
return callId;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test functions
|
||||
*/
|
||||
|
||||
template <typename State_>
|
||||
void testParentService(const boost::shared_ptr<State_>& state) {
|
||||
boost::shared_ptr<typename State_::Client> client = state->createClient();
|
||||
|
||||
int32_t gen = client->getGeneration();
|
||||
int32_t newGen = client->incrementGeneration();
|
||||
BOOST_CHECK_EQUAL(gen + 1, newGen);
|
||||
newGen = client->getGeneration();
|
||||
BOOST_CHECK_EQUAL(gen + 1, newGen);
|
||||
|
||||
client->addString("foo");
|
||||
client->addString("bar");
|
||||
client->addString("asdf");
|
||||
|
||||
vector<string> strings;
|
||||
client->getStrings(strings);
|
||||
BOOST_REQUIRE_EQUAL(3, strings.size());
|
||||
BOOST_REQUIRE_EQUAL("foo", strings[0]);
|
||||
BOOST_REQUIRE_EQUAL("bar", strings[1]);
|
||||
BOOST_REQUIRE_EQUAL("asdf", strings[2]);
|
||||
}
|
||||
|
||||
template <typename State_>
|
||||
void testChildService(const boost::shared_ptr<State_>& state) {
|
||||
boost::shared_ptr<typename State_::Client> client = state->createClient();
|
||||
|
||||
// Test calling some of the parent methids via the a child client
|
||||
int32_t gen = client->getGeneration();
|
||||
int32_t newGen = client->incrementGeneration();
|
||||
BOOST_CHECK_EQUAL(gen + 1, newGen);
|
||||
newGen = client->getGeneration();
|
||||
BOOST_CHECK_EQUAL(gen + 1, newGen);
|
||||
|
||||
// Test some of the child methods
|
||||
client->setValue(10);
|
||||
BOOST_CHECK_EQUAL(10, client->getValue());
|
||||
BOOST_CHECK_EQUAL(10, client->setValue(99));
|
||||
BOOST_CHECK_EQUAL(99, client->getValue());
|
||||
}
|
||||
|
||||
template <typename ServerTraits, typename TemplateTraits>
|
||||
void testBasicService() {
|
||||
typedef ServiceState<ServerTraits, ParentServiceTraits<TemplateTraits> > State;
|
||||
|
||||
// Start the server
|
||||
boost::shared_ptr<State> state(new State);
|
||||
ServerThread serverThread(state, true);
|
||||
|
||||
testParentService(state);
|
||||
}
|
||||
|
||||
template <typename ServerTraits, typename TemplateTraits>
|
||||
void testInheritedService() {
|
||||
typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
|
||||
|
||||
// Start the server
|
||||
boost::shared_ptr<State> state(new State);
|
||||
ServerThread serverThread(state, true);
|
||||
|
||||
testParentService(state);
|
||||
testChildService(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test to make sure that the TServerEventHandler and TProcessorEventHandler
|
||||
* methods are invoked in the correct order with the actual events.
|
||||
*/
|
||||
template <typename ServerTraits, typename TemplateTraits>
|
||||
void testEventSequencing() {
|
||||
// We use TBufferedTransport for this test, instead of TFramedTransport.
|
||||
// This way the server will start processing data as soon as it is received,
|
||||
// instead of waiting for the full request. This is necessary so we can
|
||||
// separate the preRead() and postRead() events.
|
||||
typedef ServiceState<ServerTraits,
|
||||
ChildServiceTraits<TemplateTraits>,
|
||||
TBufferedTransportFactory,
|
||||
TBufferedTransport> State;
|
||||
|
||||
// Start the server
|
||||
boost::shared_ptr<State> state(new State);
|
||||
ServerThread serverThread(state, true);
|
||||
|
||||
const boost::shared_ptr<EventLog>& log = state->getLog();
|
||||
|
||||
// Make sure we're at the end of the log
|
||||
checkNoEvents(log);
|
||||
|
||||
state->getHandler()->prepareTriggeredCall();
|
||||
|
||||
// Make sure createContext() is called after a connection has been
|
||||
// established. We open a plain socket instead of creating a client.
|
||||
boost::shared_ptr<TSocket> socket(new TSocket("127.0.0.1", state->getPort()));
|
||||
socket->open();
|
||||
|
||||
// Make sure the proper events occurred after a new connection
|
||||
uint32_t connId = checkNewConnEvents(log);
|
||||
|
||||
// Send a message header. We manually construct the request so that we
|
||||
// can test the timing for the preRead() call.
|
||||
string requestName = "getDataWait";
|
||||
string eventName = "ParentService.getDataWait";
|
||||
int32_t seqid = int32_t(time(NULL));
|
||||
TBinaryProtocol protocol(socket);
|
||||
protocol.writeMessageBegin(requestName, T_CALL, seqid);
|
||||
socket->flush();
|
||||
|
||||
// Make sure we saw the call started and pre-read events
|
||||
Event event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_CALL_STARTED, event.type);
|
||||
BOOST_CHECK_EQUAL(eventName, event.message);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
uint32_t callId = event.callId;
|
||||
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_PRE_READ, event.type);
|
||||
BOOST_CHECK_EQUAL(eventName, event.message);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callId, event.callId);
|
||||
|
||||
// Make sure there are no new events
|
||||
checkNoEvents(log);
|
||||
|
||||
// Send the rest of the request
|
||||
protocol.writeStructBegin("ParentService_getDataNotified_pargs");
|
||||
protocol.writeFieldBegin("length", apache::thrift::protocol::T_I32, 1);
|
||||
protocol.writeI32(8 * 1024 * 1024);
|
||||
protocol.writeFieldEnd();
|
||||
protocol.writeFieldStop();
|
||||
protocol.writeStructEnd();
|
||||
protocol.writeMessageEnd();
|
||||
socket->writeEnd();
|
||||
socket->flush();
|
||||
|
||||
// We should then see postRead()
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_POST_READ, event.type);
|
||||
BOOST_CHECK_EQUAL(eventName, event.message);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callId, event.callId);
|
||||
|
||||
// Then the handler should be invoked
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_CALL_GET_DATA_WAIT, event.type);
|
||||
|
||||
// The handler won't respond until we notify it.
|
||||
// Make sure there are no more events.
|
||||
checkNoEvents(log);
|
||||
|
||||
// Notify the handler that it should return
|
||||
// We just use a global lock for now, since it is easiest
|
||||
state->getHandler()->triggerPendingCalls();
|
||||
|
||||
// The handler will log a separate event before it returns
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_WAIT_RETURN, event.type);
|
||||
|
||||
// We should then see preWrite()
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_PRE_WRITE, event.type);
|
||||
BOOST_CHECK_EQUAL(eventName, event.message);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callId, event.callId);
|
||||
|
||||
// We requested more data than can be buffered, and we aren't reading it,
|
||||
// so the server shouldn't be able to finish its write yet.
|
||||
// Make sure there are no more events.
|
||||
checkNoEvents(log);
|
||||
|
||||
// Read the response header
|
||||
std::string responseName;
|
||||
int32_t responseSeqid = 0;
|
||||
apache::thrift::protocol::TMessageType responseType;
|
||||
protocol.readMessageBegin(responseName, responseType, responseSeqid);
|
||||
BOOST_CHECK_EQUAL(responseSeqid, seqid);
|
||||
BOOST_CHECK_EQUAL(requestName, responseName);
|
||||
BOOST_CHECK_EQUAL(responseType, T_REPLY);
|
||||
// Read the body. We just ignore it for now.
|
||||
protocol.skip(T_STRUCT);
|
||||
|
||||
// Now that we have read, the server should have finished sending the data
|
||||
// and called the postWrite() handler
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_POST_WRITE, event.type);
|
||||
BOOST_CHECK_EQUAL(eventName, event.message);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callId, event.callId);
|
||||
|
||||
// Call finished should be last
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_CALL_FINISHED, event.type);
|
||||
BOOST_CHECK_EQUAL(eventName, event.message);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callId, event.callId);
|
||||
|
||||
// There should be no more events
|
||||
checkNoEvents(log);
|
||||
|
||||
// Close the connection, and make sure we get a connection destroyed event
|
||||
socket->close();
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_CONN_DESTROYED, event.type);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
|
||||
// There should be no more events
|
||||
checkNoEvents(log);
|
||||
}
|
||||
|
||||
template <typename ServerTraits, typename TemplateTraits>
|
||||
void testSeparateConnections() {
|
||||
typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
|
||||
|
||||
// Start the server
|
||||
boost::shared_ptr<State> state(new State);
|
||||
ServerThread serverThread(state, true);
|
||||
|
||||
const boost::shared_ptr<EventLog>& log = state->getLog();
|
||||
|
||||
// Create a client
|
||||
boost::shared_ptr<typename State::Client> client1 = state->createClient();
|
||||
|
||||
// Make sure the expected events were logged
|
||||
uint32_t client1Id = checkNewConnEvents(log);
|
||||
|
||||
// Create a second client
|
||||
boost::shared_ptr<typename State::Client> client2 = state->createClient();
|
||||
|
||||
// Make sure the expected events were logged
|
||||
uint32_t client2Id = checkNewConnEvents(log);
|
||||
|
||||
// The two connections should have different IDs
|
||||
BOOST_CHECK_NE(client1Id, client2Id);
|
||||
|
||||
// Make a call, and check for the proper events
|
||||
int32_t value = 5;
|
||||
client1->setValue(value);
|
||||
uint32_t call1
|
||||
= checkCallEvents(log, client1Id, EventLog::ET_CALL_SET_VALUE, "ChildService.setValue");
|
||||
|
||||
// Make a call with client2
|
||||
int32_t v = client2->getValue();
|
||||
BOOST_CHECK_EQUAL(value, v);
|
||||
checkCallEvents(log, client2Id, EventLog::ET_CALL_GET_VALUE, "ChildService.getValue");
|
||||
|
||||
// Make another call with client1
|
||||
v = client1->getValue();
|
||||
BOOST_CHECK_EQUAL(value, v);
|
||||
uint32_t call2
|
||||
= checkCallEvents(log, client1Id, EventLog::ET_CALL_GET_VALUE, "ChildService.getValue");
|
||||
BOOST_CHECK_NE(call1, call2);
|
||||
|
||||
// Close the second client, and check for the appropriate events
|
||||
client2.reset();
|
||||
checkCloseEvents(log, client2Id);
|
||||
}
|
||||
|
||||
template <typename ServerTraits, typename TemplateTraits>
|
||||
void testOnewayCall() {
|
||||
typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
|
||||
|
||||
// Start the server
|
||||
boost::shared_ptr<State> state(new State);
|
||||
ServerThread serverThread(state, true);
|
||||
|
||||
const boost::shared_ptr<EventLog>& log = state->getLog();
|
||||
|
||||
// Create a client
|
||||
boost::shared_ptr<typename State::Client> client = state->createClient();
|
||||
uint32_t connId = checkNewConnEvents(log);
|
||||
|
||||
// Make a oneway call
|
||||
// It should return immediately, even though the server's handler
|
||||
// won't return right away
|
||||
state->getHandler()->prepareTriggeredCall();
|
||||
client->onewayWait();
|
||||
string callName = "ParentService.onewayWait";
|
||||
uint32_t callId = checkCallHandlerEvents(log, connId, EventLog::ET_CALL_ONEWAY_WAIT, callName);
|
||||
|
||||
// There shouldn't be any more events
|
||||
checkNoEvents(log);
|
||||
|
||||
// Trigger the handler to return
|
||||
state->getHandler()->triggerPendingCalls();
|
||||
|
||||
// The handler will log an ET_WAIT_RETURN event when it wakes up
|
||||
Event event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_WAIT_RETURN, event.type);
|
||||
|
||||
// Now we should see the async complete event, then call finished
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_ASYNC_COMPLETE, event.type);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callId, event.callId);
|
||||
BOOST_CHECK_EQUAL(callName, event.message);
|
||||
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_CALL_FINISHED, event.type);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callId, event.callId);
|
||||
BOOST_CHECK_EQUAL(callName, event.message);
|
||||
|
||||
// Destroy the client, and check for connection closed events
|
||||
client.reset();
|
||||
checkCloseEvents(log, connId);
|
||||
|
||||
checkNoEvents(log);
|
||||
}
|
||||
|
||||
template <typename ServerTraits, typename TemplateTraits>
|
||||
void testExpectedError() {
|
||||
typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
|
||||
|
||||
// Start the server
|
||||
boost::shared_ptr<State> state(new State);
|
||||
ServerThread serverThread(state, true);
|
||||
|
||||
const boost::shared_ptr<EventLog>& log = state->getLog();
|
||||
|
||||
// Create a client
|
||||
boost::shared_ptr<typename State::Client> client = state->createClient();
|
||||
uint32_t connId = checkNewConnEvents(log);
|
||||
|
||||
// Send the exceptionWait() call
|
||||
state->getHandler()->prepareTriggeredCall();
|
||||
string message = "test 1234 test";
|
||||
client->send_exceptionWait(message);
|
||||
string callName = "ParentService.exceptionWait";
|
||||
uint32_t callId = checkCallHandlerEvents(log, connId, EventLog::ET_CALL_EXCEPTION_WAIT, callName);
|
||||
|
||||
// There shouldn't be any more events
|
||||
checkNoEvents(log);
|
||||
|
||||
// Trigger the handler to return
|
||||
state->getHandler()->triggerPendingCalls();
|
||||
|
||||
// The handler will log an ET_WAIT_RETURN event when it wakes up
|
||||
Event event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_WAIT_RETURN, event.type);
|
||||
|
||||
// Now receive the response
|
||||
try {
|
||||
client->recv_exceptionWait();
|
||||
BOOST_FAIL("expected MyError to be thrown");
|
||||
} catch (const MyError& e) {
|
||||
BOOST_CHECK_EQUAL(message, e.message);
|
||||
// Check if std::exception::what() is handled properly
|
||||
size_t message_pos = std::string(e.what()).find("TException - service has thrown: MyError");
|
||||
BOOST_CHECK_NE(message_pos, std::string::npos);
|
||||
}
|
||||
|
||||
// Now we should see the events for a normal call finish
|
||||
checkCallPostHandlerEvents(log, connId, callId, callName);
|
||||
|
||||
// There shouldn't be any more events
|
||||
checkNoEvents(log);
|
||||
|
||||
// Destroy the client, and check for connection closed events
|
||||
client.reset();
|
||||
checkCloseEvents(log, connId);
|
||||
|
||||
checkNoEvents(log);
|
||||
}
|
||||
|
||||
template <typename ServerTraits, typename TemplateTraits>
|
||||
void testUnexpectedError() {
|
||||
typedef ServiceState<ServerTraits, ChildServiceTraits<TemplateTraits> > State;
|
||||
|
||||
// Start the server
|
||||
boost::shared_ptr<State> state(new State);
|
||||
ServerThread serverThread(state, true);
|
||||
|
||||
const boost::shared_ptr<EventLog>& log = state->getLog();
|
||||
|
||||
// Create a client
|
||||
boost::shared_ptr<typename State::Client> client = state->createClient();
|
||||
uint32_t connId = checkNewConnEvents(log);
|
||||
|
||||
// Send the unexpectedExceptionWait() call
|
||||
state->getHandler()->prepareTriggeredCall();
|
||||
string message = "1234 test 5678";
|
||||
client->send_unexpectedExceptionWait(message);
|
||||
string callName = "ParentService.unexpectedExceptionWait";
|
||||
uint32_t callId
|
||||
= checkCallHandlerEvents(log, connId, EventLog::ET_CALL_UNEXPECTED_EXCEPTION_WAIT, callName);
|
||||
|
||||
// There shouldn't be any more events
|
||||
checkNoEvents(log);
|
||||
|
||||
// Trigger the handler to return
|
||||
state->getHandler()->triggerPendingCalls();
|
||||
|
||||
// The handler will log an ET_WAIT_RETURN event when it wakes up
|
||||
Event event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_WAIT_RETURN, event.type);
|
||||
|
||||
// Now receive the response
|
||||
try {
|
||||
client->recv_unexpectedExceptionWait();
|
||||
BOOST_FAIL("expected TApplicationError to be thrown");
|
||||
} catch (const TApplicationException&) {
|
||||
}
|
||||
|
||||
// Now we should see a handler error event
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_HANDLER_ERROR, event.type);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callId, event.callId);
|
||||
BOOST_CHECK_EQUAL(callName, event.message);
|
||||
|
||||
// pre-write and post-write events aren't generated after a handler error
|
||||
// (Even for non-oneway calls where a response is written.)
|
||||
//
|
||||
// A call finished event is logged when the call context is destroyed
|
||||
event = log->waitForEvent();
|
||||
BOOST_CHECK_EQUAL(EventLog::ET_CALL_FINISHED, event.type);
|
||||
BOOST_CHECK_EQUAL(connId, event.connectionId);
|
||||
BOOST_CHECK_EQUAL(callId, event.callId);
|
||||
BOOST_CHECK_EQUAL(callName, event.message);
|
||||
|
||||
// There shouldn't be any more events
|
||||
checkNoEvents(log);
|
||||
|
||||
// Destroy the client, and check for connection closed events
|
||||
client.reset();
|
||||
checkCloseEvents(log, connId);
|
||||
|
||||
checkNoEvents(log);
|
||||
}
|
||||
|
||||
// Macro to define simple tests that can be used with all server types
|
||||
#define DEFINE_SIMPLE_TESTS(Server, Template) \
|
||||
BOOST_AUTO_TEST_CASE(Server##_##Template##_basicService) { \
|
||||
testBasicService<Server##Traits, Template##Traits>(); \
|
||||
} \
|
||||
BOOST_AUTO_TEST_CASE(Server##_##Template##_inheritedService) { \
|
||||
testInheritedService<Server##Traits, Template##Traits>(); \
|
||||
} \
|
||||
BOOST_AUTO_TEST_CASE(Server##_##Template##_oneway) { \
|
||||
testOnewayCall<Server##Traits, Template##Traits>(); \
|
||||
} \
|
||||
BOOST_AUTO_TEST_CASE(Server##_##Template##_exception) { \
|
||||
testExpectedError<Server##Traits, Template##Traits>(); \
|
||||
} \
|
||||
BOOST_AUTO_TEST_CASE(Server##_##Template##_unexpectedException) { \
|
||||
testUnexpectedError<Server##Traits, Template##Traits>(); \
|
||||
}
|
||||
|
||||
// Tests that require the server to process multiple connections concurrently
|
||||
// (i.e., not TSimpleServer)
|
||||
#define DEFINE_CONCURRENT_SERVER_TESTS(Server, Template) \
|
||||
BOOST_AUTO_TEST_CASE(Server##_##Template##_separateConnections) { \
|
||||
testSeparateConnections<Server##Traits, Template##Traits>(); \
|
||||
}
|
||||
|
||||
// The testEventSequencing() test manually generates a request for the server,
|
||||
// and doesn't work with TFramedTransport. Therefore we can't test it with
|
||||
// TNonblockingServer.
|
||||
#define DEFINE_NOFRAME_TESTS(Server, Template) \
|
||||
BOOST_AUTO_TEST_CASE(Server##_##Template##_eventSequencing) { \
|
||||
testEventSequencing<Server##Traits, Template##Traits>(); \
|
||||
}
|
||||
|
||||
#define DEFINE_TNONBLOCKINGSERVER_TESTS(Server, Template) \
|
||||
DEFINE_SIMPLE_TESTS(Server, Template) \
|
||||
DEFINE_CONCURRENT_SERVER_TESTS(Server, Template)
|
||||
|
||||
#define DEFINE_ALL_SERVER_TESTS(Server, Template) \
|
||||
DEFINE_SIMPLE_TESTS(Server, Template) \
|
||||
DEFINE_CONCURRENT_SERVER_TESTS(Server, Template) \
|
||||
DEFINE_NOFRAME_TESTS(Server, Template)
|
||||
|
||||
DEFINE_ALL_SERVER_TESTS(TThreadedServer, Templated)
|
||||
DEFINE_ALL_SERVER_TESTS(TThreadedServer, Untemplated)
|
||||
DEFINE_ALL_SERVER_TESTS(TThreadPoolServer, Templated)
|
||||
DEFINE_ALL_SERVER_TESTS(TThreadPoolServer, Untemplated)
|
||||
|
||||
DEFINE_TNONBLOCKINGSERVER_TESTS(TNonblockingServer, Templated)
|
||||
DEFINE_TNONBLOCKINGSERVER_TESTS(TNonblockingServer, Untemplated)
|
||||
DEFINE_TNONBLOCKINGSERVER_TESTS(TNonblockingServerNoThreads, Templated)
|
||||
DEFINE_TNONBLOCKINGSERVER_TESTS(TNonblockingServerNoThreads, Untemplated)
|
||||
|
||||
DEFINE_SIMPLE_TESTS(TSimpleServer, Templated)
|
||||
DEFINE_SIMPLE_TESTS(TSimpleServer, Untemplated)
|
||||
DEFINE_NOFRAME_TESTS(TSimpleServer, Templated)
|
||||
DEFINE_NOFRAME_TESTS(TSimpleServer, Untemplated)
|
||||
|
||||
// TODO: We should test TEventServer in the future.
|
||||
// For now, it is known not to work correctly with TProcessorEventHandler.
|
||||
#ifdef BOOST_TEST_DYN_LINK
|
||||
bool init_unit_test_suite() {
|
||||
unit_test::framework::master_test_suite().p_name.value = "ProcessorTest";
|
||||
return true;
|
||||
}
|
||||
|
||||
int main( int argc, char* argv[] ) {
|
||||
return ::boost::unit_test::unit_test_main(&init_unit_test_suite,argc,argv);
|
||||
}
|
||||
#else
|
||||
unit_test::test_suite* init_unit_test_suite(int argc, char* argv[]) {
|
||||
THRIFT_UNUSED_VARIABLE(argc);
|
||||
THRIFT_UNUSED_VARIABLE(argv);
|
||||
unit_test::framework::master_test_suite().p_name.value = "ProcessorTest";
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
150
vendor/git.apache.org/thrift.git/lib/cpp/test/processor/ServerThread.cpp
generated
vendored
Normal file
150
vendor/git.apache.org/thrift.git/lib/cpp/test/processor/ServerThread.cpp
generated
vendored
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 _THRIFT_TEST_SERVERTHREAD_TCC_
|
||||
#define _THRIFT_TEST_SERVERTHREAD_TCC_ 1
|
||||
|
||||
#include "ServerThread.h"
|
||||
|
||||
#include <thrift/concurrency/PlatformThreadFactory.h>
|
||||
#include <thrift/concurrency/ThreadManager.h>
|
||||
#include <thrift/server/TThreadPoolServer.h>
|
||||
#include <thrift/transport/TBufferTransports.h>
|
||||
#include <thrift/transport/TServerSocket.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace test {
|
||||
|
||||
void ServerThread::start() {
|
||||
assert(!running_);
|
||||
running_ = true;
|
||||
|
||||
// Start the other thread
|
||||
concurrency::PlatformThreadFactory threadFactory;
|
||||
threadFactory.setDetached(false);
|
||||
thread_ = threadFactory.newThread(helper_);
|
||||
|
||||
thread_->start();
|
||||
|
||||
// Wait on the other thread to tell us that it has successfully
|
||||
// bound to the port and started listening (or until an error occurs).
|
||||
concurrency::Synchronized s(serverMonitor_);
|
||||
while (!serving_ && !error_) {
|
||||
serverMonitor_.waitForever();
|
||||
}
|
||||
|
||||
if (error_) {
|
||||
throw transport::TTransportException(transport::TTransportException::NOT_OPEN,
|
||||
"failed to bind on server socket");
|
||||
}
|
||||
}
|
||||
|
||||
void ServerThread::stop() {
|
||||
if (!running_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Tell the server to stop
|
||||
server_->stop();
|
||||
running_ = false;
|
||||
|
||||
// Wait for the server thread to exit
|
||||
//
|
||||
// Note: this only works if all client connections have closed. The servers
|
||||
// generally wait for everything to be closed before exiting; there currently
|
||||
// isn't a way to tell them to just exit now, and shut down existing
|
||||
// connections.
|
||||
thread_->join();
|
||||
}
|
||||
|
||||
void ServerThread::run() {
|
||||
/*
|
||||
* Try binding to several ports, in case the one we want is already in use.
|
||||
*/
|
||||
port_ = 12345;
|
||||
unsigned int maxRetries = 10;
|
||||
for (unsigned int n = 0; n < maxRetries; ++n) {
|
||||
// Create the server
|
||||
server_ = serverState_->createServer(port_);
|
||||
// Install our helper as the server event handler, so that our
|
||||
// preServe() method will be called once we've successfully bound to
|
||||
// the port and are about to start listening.
|
||||
server_->setServerEventHandler(helper_);
|
||||
|
||||
try {
|
||||
// Try to serve requests
|
||||
server_->serve();
|
||||
} catch (const TException&) {
|
||||
// TNonblockingServer throws a generic TException if it fails to bind.
|
||||
// If we get a TException, we'll optimistically assume the bind failed.
|
||||
++port_;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Seriously? serve() is pretty lame. If it fails to start serving it
|
||||
// just returns rather than throwing an exception.
|
||||
//
|
||||
// We have to use our preServe() hook to tell if serve() successfully
|
||||
// started serving and is returning because stop() is called, or if it just
|
||||
// failed to start serving in the first place.
|
||||
concurrency::Synchronized s(serverMonitor_);
|
||||
if (serving_) {
|
||||
// Oh good, we started serving and are exiting because
|
||||
// we're trying to stop.
|
||||
serving_ = false;
|
||||
return;
|
||||
} else {
|
||||
// We never started serving, probably because we failed to bind to the
|
||||
// port. Increment the port number and try again.
|
||||
++port_;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// We failed to bind on any port.
|
||||
concurrency::Synchronized s(serverMonitor_);
|
||||
error_ = true;
|
||||
serverMonitor_.notify();
|
||||
}
|
||||
|
||||
void ServerThread::preServe() {
|
||||
// We bound to the port successfully, and are about to start serving requests
|
||||
serverState_->bindSuccessful(port_);
|
||||
|
||||
// Set the real server event handler (replacing ourself)
|
||||
boost::shared_ptr<server::TServerEventHandler> serverEventHandler
|
||||
= serverState_->getServerEventHandler();
|
||||
server_->setServerEventHandler(serverEventHandler);
|
||||
|
||||
// Notify the main thread that we have successfully started serving requests
|
||||
concurrency::Synchronized s(serverMonitor_);
|
||||
serving_ = true;
|
||||
serverMonitor_.notify();
|
||||
|
||||
// Invoke preServe() on the real event handler, since we ate
|
||||
// the original preServe() event.
|
||||
if (serverEventHandler) {
|
||||
serverEventHandler->preServe();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // apache::thrift::test
|
||||
|
||||
#endif // _THRIFT_TEST_SERVERTHREAD_TCC_
|
136
vendor/git.apache.org/thrift.git/lib/cpp/test/processor/ServerThread.h
generated
vendored
Normal file
136
vendor/git.apache.org/thrift.git/lib/cpp/test/processor/ServerThread.h
generated
vendored
Normal file
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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 _THRIFT_TEST_SERVERTHREAD_H_
|
||||
#define _THRIFT_TEST_SERVERTHREAD_H_ 1
|
||||
|
||||
#include <thrift/TProcessor.h>
|
||||
#include <thrift/protocol/TProtocol.h>
|
||||
#include <thrift/server/TServer.h>
|
||||
#include <thrift/transport/TTransport.h>
|
||||
|
||||
#include "EventLog.h"
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace test {
|
||||
|
||||
/**
|
||||
* A helper class to tell ServerThread how to create the server
|
||||
*/
|
||||
class ServerState {
|
||||
public:
|
||||
virtual ~ServerState() {}
|
||||
|
||||
/**
|
||||
* Create a server to listen on the specified port.
|
||||
*
|
||||
* If the server returned fails to bind to the specified port when serve() is
|
||||
* called on it, createServer() may be called again on a different port.
|
||||
*/
|
||||
virtual boost::shared_ptr<server::TServer> createServer(uint16_t port) = 0;
|
||||
|
||||
/**
|
||||
* Get the TServerEventHandler to set on the server.
|
||||
*
|
||||
* This is only called after the server successfully binds and is about to
|
||||
* start serving traffic. It is invoked from the server thread, rather than
|
||||
* the main thread.
|
||||
*/
|
||||
virtual boost::shared_ptr<server::TServerEventHandler> getServerEventHandler() {
|
||||
return boost::shared_ptr<server::TServerEventHandler>();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called in the server thread after server binding succeeds.
|
||||
*
|
||||
* Subclasses may override this method if they wish to record the final
|
||||
* port that was used for the server.
|
||||
*/
|
||||
virtual void bindSuccessful(uint16_t /*port*/) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* ServerThread starts a thrift server running in a separate thread.
|
||||
*/
|
||||
class ServerThread {
|
||||
public:
|
||||
ServerThread(const boost::shared_ptr<ServerState>& state, bool autoStart)
|
||||
: helper_(new Helper(this)),
|
||||
port_(0),
|
||||
running_(false),
|
||||
serving_(false),
|
||||
error_(false),
|
||||
serverState_(state) {
|
||||
if (autoStart) {
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
uint16_t getPort() const { return port_; }
|
||||
|
||||
~ServerThread() {
|
||||
if (running_) {
|
||||
try {
|
||||
stop();
|
||||
} catch (...) {
|
||||
GlobalOutput.printf("error shutting down server");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
// Annoying. thrift forces us to use shared_ptr, so we have to use
|
||||
// a helper class that we can allocate on the heap and give to thrift.
|
||||
// It would be simpler if we could just make Runnable and TServerEventHandler
|
||||
// private base classes of ServerThread.
|
||||
class Helper : public concurrency::Runnable, public server::TServerEventHandler {
|
||||
public:
|
||||
Helper(ServerThread* serverThread) : serverThread_(serverThread) {}
|
||||
|
||||
void run() { serverThread_->run(); }
|
||||
|
||||
void preServe() { serverThread_->preServe(); }
|
||||
|
||||
private:
|
||||
ServerThread* serverThread_;
|
||||
};
|
||||
|
||||
void run();
|
||||
void preServe();
|
||||
|
||||
boost::shared_ptr<Helper> helper_;
|
||||
|
||||
uint16_t port_;
|
||||
bool running_;
|
||||
bool serving_;
|
||||
bool error_;
|
||||
concurrency::Monitor serverMonitor_;
|
||||
|
||||
boost::shared_ptr<ServerState> serverState_;
|
||||
boost::shared_ptr<server::TServer> server_;
|
||||
boost::shared_ptr<concurrency::Thread> thread_;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // apache::thrift::test
|
||||
|
||||
#endif // _THRIFT_TEST_SERVERTHREAD_H_
|
22
vendor/git.apache.org/thrift.git/lib/cpp/test/processor/proc.thrift
generated
vendored
Normal file
22
vendor/git.apache.org/thrift.git/lib/cpp/test/processor/proc.thrift
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
namespace cpp apache.thrift.test
|
||||
|
||||
exception MyError {
|
||||
1: string message
|
||||
}
|
||||
|
||||
service ParentService {
|
||||
i32 incrementGeneration()
|
||||
i32 getGeneration()
|
||||
void addString(1: string s)
|
||||
list<string> getStrings()
|
||||
|
||||
binary getDataWait(1: i32 length)
|
||||
oneway void onewayWait()
|
||||
void exceptionWait(1: string message) throws (2: MyError error)
|
||||
void unexpectedExceptionWait(1: string message)
|
||||
}
|
||||
|
||||
service ChildService extends ParentService {
|
||||
i32 setValue(1: i32 value)
|
||||
i32 getValue()
|
||||
}
|
32
vendor/git.apache.org/thrift.git/lib/cpp/test/qt/CMakeLists.txt
generated
vendored
Normal file
32
vendor/git.apache.org/thrift.git/lib/cpp/test/qt/CMakeLists.txt
generated
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
find_package(Qt5 REQUIRED COMPONENTS Test Network)
|
||||
set(TQTcpServerTest_Qt5_SOURCES
|
||||
TQTcpServerTest.cpp
|
||||
)
|
||||
add_executable(TQTcpServerTest_Qt5 ${TQTcpServerTest_Qt5_SOURCES})
|
||||
target_link_libraries(TQTcpServerTest_Qt5 testgencpp_cob)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(TQTcpServerTest_Qt5 thriftqt5)
|
||||
LINK_AGAINST_THRIFT_LIBRARY(TQTcpServerTest_Qt5 thrift)
|
||||
target_link_libraries(TQTcpServerTest_Qt5 Qt5::Test Qt5::Network)
|
||||
|
||||
add_test(NAME TQTcpServerTest_Qt5 COMMAND TQTcpServerTest_Qt5)
|
||||
|
114
vendor/git.apache.org/thrift.git/lib/cpp/test/qt/TQTcpServerTest.cpp
generated
vendored
Normal file
114
vendor/git.apache.org/thrift.git/lib/cpp/test/qt/TQTcpServerTest.cpp
generated
vendored
Normal file
|
@ -0,0 +1,114 @@
|
|||
#define BOOST_TEST_MODULE TQTcpServerTest
|
||||
#include <QTest>
|
||||
#include <iostream>
|
||||
|
||||
#include <QTcpServer>
|
||||
#include <QTcpSocket>
|
||||
#include <QHostAddress>
|
||||
#include <QThread>
|
||||
|
||||
#ifndef Q_MOC_RUN
|
||||
#include <boost/smart_ptr.hpp>
|
||||
#include "thrift/protocol/TBinaryProtocol.h"
|
||||
#include "thrift/async/TAsyncProcessor.h"
|
||||
#include "thrift/qt/TQTcpServer.h"
|
||||
#include "thrift/qt/TQIODeviceTransport.h"
|
||||
|
||||
#include "gen-cpp/ParentService.h"
|
||||
#endif
|
||||
|
||||
using namespace apache::thrift;
|
||||
|
||||
struct AsyncHandler : public test::ParentServiceCobSvIf {
|
||||
std::vector<std::string> strings;
|
||||
virtual void addString(tcxx::function<void()> cob, const std::string& s) {
|
||||
strings.push_back(s);
|
||||
cob();
|
||||
}
|
||||
virtual void getStrings(tcxx::function<void(std::vector<std::string> const& _return)> cob) {
|
||||
cob(strings);
|
||||
}
|
||||
|
||||
// Overrides not used in this test
|
||||
virtual void incrementGeneration(tcxx::function<void(int32_t const& _return)> cob) {}
|
||||
virtual void getGeneration(tcxx::function<void(int32_t const& _return)> cob) {}
|
||||
virtual void getDataWait(tcxx::function<void(std::string const& _return)> cob,
|
||||
const int32_t length) {}
|
||||
virtual void onewayWait(tcxx::function<void()> cob) {}
|
||||
virtual void exceptionWait(
|
||||
tcxx::function<void()> cob,
|
||||
tcxx::function<void(::apache::thrift::TDelayedException* _throw)> /* exn_cob */,
|
||||
const std::string& message) {}
|
||||
virtual void unexpectedExceptionWait(tcxx::function<void()> cob, const std::string& message) {}
|
||||
};
|
||||
|
||||
class TQTcpServerTest : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
void cleanupTestCase();
|
||||
void test_communicate();
|
||||
|
||||
private:
|
||||
boost::shared_ptr<QThread> serverThread;
|
||||
boost::shared_ptr<async::TQTcpServer> server;
|
||||
boost::shared_ptr<test::ParentServiceClient> client;
|
||||
};
|
||||
|
||||
void TQTcpServerTest::initTestCase() {
|
||||
// setup server
|
||||
boost::shared_ptr<QTcpServer> serverSocket = boost::make_shared<QTcpServer>();
|
||||
server.reset(new async::TQTcpServer(serverSocket,
|
||||
boost::make_shared<test::ParentServiceAsyncProcessor>(
|
||||
boost::make_shared<AsyncHandler>()),
|
||||
boost::make_shared<protocol::TBinaryProtocolFactory>()));
|
||||
QVERIFY(serverSocket->listen(QHostAddress::LocalHost));
|
||||
int port = serverSocket->serverPort();
|
||||
QVERIFY(port > 0);
|
||||
|
||||
//setup server thread and move server to it
|
||||
serverThread.reset(new QThread());
|
||||
serverSocket->moveToThread(serverThread.get());
|
||||
server->moveToThread(serverThread.get());
|
||||
serverThread->start();
|
||||
|
||||
// setup client
|
||||
boost::shared_ptr<QTcpSocket> socket = boost::make_shared<QTcpSocket>();
|
||||
client.reset(new test::ParentServiceClient(boost::make_shared<protocol::TBinaryProtocol>(
|
||||
boost::make_shared<transport::TQIODeviceTransport>(socket))));
|
||||
socket->connectToHost(QHostAddress::LocalHost, port);
|
||||
QVERIFY(socket->waitForConnected());
|
||||
}
|
||||
|
||||
void TQTcpServerTest::cleanupTestCase() {
|
||||
//first, stop the thread which holds the server
|
||||
serverThread->quit();
|
||||
serverThread->wait();
|
||||
// now, it is safe to delete the server
|
||||
server.reset();
|
||||
// delete thread now
|
||||
serverThread.reset();
|
||||
|
||||
// cleanup client
|
||||
client.reset();
|
||||
}
|
||||
|
||||
void TQTcpServerTest::test_communicate() {
|
||||
client->addString("foo");
|
||||
client->addString("bar");
|
||||
|
||||
std::vector<std::string> reply;
|
||||
client->getStrings(reply);
|
||||
QCOMPARE(QString::fromStdString(reply[0]), QString("foo"));
|
||||
QCOMPARE(QString::fromStdString(reply[1]), QString("bar"));
|
||||
}
|
||||
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
|
||||
QTEST_GUILESS_MAIN(TQTcpServerTest);
|
||||
#else
|
||||
#undef QT_GUI_LIB
|
||||
QTEST_MAIN(TQTcpServerTest);
|
||||
#endif
|
||||
#include "TQTcpServerTest.moc"
|
Loading…
Add table
Add a link
Reference in a new issue