thrift/test/OptionalRequiredTest.cpp

247 lines
5.9 KiB
C++

/*
* 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 <cassert>
#include <map>
#include <iostream>
#include <protocol/TDebugProtocol.h>
#include <protocol/TBinaryProtocol.h>
#include <transport/TBufferTransports.h>
#include "gen-cpp/OptionalRequiredTest_types.h"
using std::cout;
using std::endl;
using std::map;
using std::string;
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;
}
assert(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);
}
int main() {
cout << "This old school struct should have three fields." << endl;
{
OldSchool o;
cout << ThriftDebugString(o) << endl;
}
cout << endl;
cout << "Setting a value before setting isset." << endl;
{
Simple s;
cout << ThriftDebugString(s) << endl;
s.im_optional = 10;
cout << ThriftDebugString(s) << endl;
s.__isset.im_optional = true;
cout << ThriftDebugString(s) << endl;
}
cout << endl;
cout << "Setting isset before setting a value." << endl;
{
Simple s;
cout << ThriftDebugString(s) << endl;
s.__isset.im_optional = true;
cout << ThriftDebugString(s) << endl;
s.im_optional = 10;
cout << ThriftDebugString(s) << endl;
}
cout << endl;
// Write-to-read with optional fields.
{
Simple s1, s2, s3;
s1.im_optional = 10;
assert(!s1.__isset.im_default);
//assert(!s1.__isset.im_required); // Compile error.
assert(!s1.__isset.im_optional);
write_to_read(s1, s2);
assert( s2.__isset.im_default);
//assert( s2.__isset.im_required); // Compile error.
assert(!s2.__isset.im_optional);
assert(s3.im_optional == 0);
s1.__isset.im_optional = true;
write_to_read(s1, s3);
assert( s3.__isset.im_default);
//assert( s3.__isset.im_required); // Compile error.
assert( s3.__isset.im_optional);
assert(s3.im_optional == 10);
}
// Writing between optional and default.
{
Tricky1 t1;
Tricky2 t2;
t2.im_optional = 10;
write_to_read(t2, t1);
write_to_read(t1, t2);
assert(!t1.__isset.im_default);
assert( t2.__isset.im_optional);
assert(t1.im_default == t2.im_optional);
assert(t1.im_default == 0);
}
// Writing between default and required.
{
Tricky1 t1;
Tricky3 t3;
write_to_read(t1, t3);
write_to_read(t3, t1);
assert(t1.__isset.im_default);
}
// Writing between optional and required.
{
Tricky2 t2;
Tricky3 t3;
t2.__isset.im_optional = true;
write_to_read(t2, t3);
write_to_read(t3, t2);
}
// Mu-hu-ha-ha-ha!
{
Tricky2 t2;
Tricky3 t3;
try {
write_to_read(t2, t3);
abort();
}
catch (TProtocolException& ex) {}
write_to_read(t3, t2);
assert(t2.__isset.im_optional);
}
cout << "Complex struct, simple test." << endl;
{
Complex c;
cout << ThriftDebugString(c) << endl;
}
{
Tricky1 t1;
Tricky2 t2;
// Compile error.
//(void)(t1 == t2);
}
{
OldSchool o1, o2, o3;
assert(o1 == o2);
o1.im_int = o2.im_int = 10;
assert(o1 == o2);
o1.__isset.im_int = true;
o2.__isset.im_int = false;
assert(o1 == o2);
o1.im_int = 20;
o1.__isset.im_int = false;
assert(o1 != o2);
o1.im_int = 10;
assert(o1 == o2);
o1.im_str = o2.im_str = "foo";
assert(o1 == o2);
o1.__isset.im_str = o2.__isset.im_str = true;
assert(o1 == o2);
map<int32_t,string> mymap;
mymap[1] = "bar";
mymap[2] = "baz";
o1.im_big.push_back(map<int32_t,string>());
assert(o1 != o2);
o2.im_big.push_back(map<int32_t,string>());
assert(o1 == o2);
o2.im_big.push_back(mymap);
assert(o1 != o2);
o1.im_big.push_back(mymap);
assert(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);
assert(o1 != o2);
o1.im_big.back()[3] = "qux";
assert(o1 == o2);
o3.read(&protocol);
o3.im_big.push_back(mymap);
assert(o1 == o3);
//cout << ThriftDebugString(o3) << endl;
}
{
Tricky2 t1, t2;
assert(t1.__isset.im_optional == false);
assert(t2.__isset.im_optional == false);
assert(t1 == t2);
t1.im_optional = 5;
assert(t1 == t2);
t2.im_optional = 5;
assert(t1 == t2);
t1.__isset.im_optional = true;
assert(t1 != t2);
t2.__isset.im_optional = true;
assert(t1 == t2);
t1.im_optional = 10;
assert(t1 != t2);
t2.__isset.im_optional = false;
assert(t1 != t2);
}
return 0;
}