Repository: thrift Updated Branches: refs/heads/master 83cd3e8d4 -> 1f6e380c5
THRIFT-727 - C++: what() method of generated exceptions will provide more information Patch: Anna Dymek <[email protected]> Client: C++ This closes #469 Project: http://git-wip-us.apache.org/repos/asf/thrift/repo Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/3b115dfa Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/3b115dfa Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/3b115dfa Branch: refs/heads/master Commit: 3b115dfa614cfac7af86d81d99f69b381508b75e Parents: 83cd3e8 Author: Konrad Grochowski <[email protected]> Authored: Mon May 18 17:58:36 2015 +0200 Committer: Konrad Grochowski <[email protected]> Committed: Mon May 18 19:47:23 2015 +0200 ---------------------------------------------------------------------- compiler/cpp/src/generate/t_cpp_generator.cc | 58 ++++++++++++++++++++++- lib/cpp/test/processor/ProcessorTest.cpp | 3 ++ tutorial/c_glib/c_glib_server.c | 4 +- tutorial/cpp/CppClient.cpp | 1 + tutorial/cpp/CppServer.cpp | 4 +- tutorial/d/server.d | 4 +- tutorial/erl/server.erl | 4 +- tutorial/haxe/src/CalculatorHandler.hx | 4 +- tutorial/hs/HaskellServer.hs | 2 +- tutorial/java/src/CalculatorHandler.java | 4 +- tutorial/nodejs/NodeServer.js | 4 +- tutorial/nodejs/NodeServerPromise.js | 4 +- tutorial/ocaml/CalcServer.ml | 2 +- tutorial/perl/PerlServer.pl | 4 +- tutorial/php/PhpServer.php | 4 +- tutorial/py.tornado/PythonServer.py | 4 +- tutorial/py.twisted/PythonServer.py | 4 +- tutorial/py/PythonServer.py | 4 +- tutorial/rb/RubyServer.rb | 4 +- tutorial/tutorial.thrift | 2 +- 20 files changed, 92 insertions(+), 32 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/compiler/cpp/src/generate/t_cpp_generator.cc ---------------------------------------------------------------------- diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc index 3edd7c8..426434f 100644 --- a/compiler/cpp/src/generate/t_cpp_generator.cc +++ b/compiler/cpp/src/generate/t_cpp_generator.cc @@ -138,6 +138,7 @@ public: void generate_struct_result_writer(std::ofstream& out, t_struct* tstruct, bool pointers = false); void generate_struct_swap(std::ofstream& out, t_struct* tstruct); void generate_struct_ostream_operator(std::ofstream& out, t_struct* tstruct); + void generate_exception_what_method(std::ofstream& out, t_struct* tstruct); /** * Service-level generation functions @@ -239,6 +240,9 @@ public: bool include_values); void generate_struct_ostream_operator_decl(std::ofstream& f, t_struct* tstruct); + void generate_exception_what_method_decl(std::ofstream& f, + t_struct* tstruct, + bool external = false); // These handles checking gen_dense_ and checking for duplicates. void generate_local_reflection(std::ofstream& out, t_type* ttype, bool is_definition); @@ -767,6 +771,9 @@ void t_cpp_generator::generate_cpp_struct(t_struct* tstruct, bool is_exception) generate_move_assignment_operator(f_types_impl_, tstruct); } generate_struct_ostream_operator(f_types_impl_, tstruct); + if (is_exception) { + generate_exception_what_method(f_types_impl_, tstruct); + } } void t_cpp_generator::generate_copy_constructor(ofstream& out, @@ -1113,7 +1120,15 @@ void t_cpp_generator::generate_struct_declaration(ofstream& out, // ostream operator<< out << indent() << "friend "; generate_struct_ostream_operator_decl(out, tstruct); - out << ";" << endl; + out << ";" << endl << endl; + + // std::exception::what() + if (is_exception) { + out << indent() << "mutable std::string thriftTExceptionMessageHolder_;" << endl; + out << indent(); + generate_exception_what_method_decl(out, tstruct, false); + out << ";" << endl; + } indent_down(); indent(out) << "};" << endl << endl; @@ -1626,6 +1641,16 @@ void t_cpp_generator::generate_struct_ostream_operator_decl(std::ofstream& out, out << "std::ostream& operator<<(std::ostream& out, const " << tstruct->get_name() << "& obj)"; } +void t_cpp_generator::generate_exception_what_method_decl(std::ofstream& out, + t_struct* tstruct, + bool external) { + out << "const char* "; + if (external) { + out << tstruct->get_name() << "::"; + } + out << "what() const throw()"; +} + namespace struct_ostream_operator_generator { void generate_required_field_value(std::ofstream& out, const t_field* field) { out << " << to_string(obj." << field->get_name() << ")"; @@ -1700,6 +1725,37 @@ void t_cpp_generator::generate_struct_ostream_operator(std::ofstream& out, t_str } /** + * Generates what() method for exceptions + */ +void t_cpp_generator::generate_exception_what_method(std::ofstream& out, t_struct* tstruct) { + out << indent(); + generate_exception_what_method_decl(out, tstruct, true); + out << " {" << endl; + + indent_up(); + out << indent() << "try {" << endl; + + indent_up(); + out << indent() << "std::stringstream ss;" << endl; + out << indent() << "ss << \"TException - service has thrown: \" << *this;" << endl; + out << indent() << "this->thriftTExceptionMessageHolder_ = ss.str();" << endl; + out << indent() << "return this->thriftTExceptionMessageHolder_.c_str();" << endl; + indent_down(); + + out << indent() << "} catch (const std::exception& e) {" << endl; + + indent_up(); + out << indent() << "return \"TException - service has thrown: " << tstruct->get_name() << "\";" + << endl; + indent_down(); + + out << indent() << "}" << endl; + + indent_down(); + out << "}" << endl << endl; +} + +/** * Generates a thrift service. In C++, this comprises an entirely separate * header and source file. The header file defines the methods and includes * the data types defined in the main header file, and the implementation http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/lib/cpp/test/processor/ProcessorTest.cpp ---------------------------------------------------------------------- diff --git a/lib/cpp/test/processor/ProcessorTest.cpp b/lib/cpp/test/processor/ProcessorTest.cpp index 655f481..40d926e 100644 --- a/lib/cpp/test/processor/ProcessorTest.cpp +++ b/lib/cpp/test/processor/ProcessorTest.cpp @@ -765,6 +765,9 @@ void testExpectedError() { 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 http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/c_glib/c_glib_server.c ---------------------------------------------------------------------- diff --git a/tutorial/c_glib/c_glib_server.c b/tutorial/c_glib/c_glib_server.c index a20ab54..000d97c 100644 --- a/tutorial/c_glib/c_glib_server.c +++ b/tutorial/c_glib/c_glib_server.c @@ -231,7 +231,7 @@ tutorial_calculator_handler_calculate (CalculatorIf *iface, setting the corresponding output parameter to a new instance of its type and returning FALSE. */ *ouch = g_object_new (TYPE_INVALID_OPERATION, - "what", op, + "whatOp", op, "why", g_strdup ("Cannot divide by 0"), NULL); result = FALSE; @@ -249,7 +249,7 @@ tutorial_calculator_handler_calculate (CalculatorIf *iface, default: *ouch = g_object_new (TYPE_INVALID_OPERATION, - "what", op, + "whatOp", op, "why", g_strdup ("Invalid Operation"), NULL); result = FALSE; http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/cpp/CppClient.cpp ---------------------------------------------------------------------- diff --git a/tutorial/cpp/CppClient.cpp b/tutorial/cpp/CppClient.cpp index 258cbd6..2763fee 100644 --- a/tutorial/cpp/CppClient.cpp +++ b/tutorial/cpp/CppClient.cpp @@ -58,6 +58,7 @@ int main() { } catch (InvalidOperation& io) { cout << "InvalidOperation: " << io.why << endl; // or using generated operator<<: cout << io << endl; + // or by using std::exception native method what(): cout << io.what() << endl; } work.op = Operation::SUBTRACT; http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/cpp/CppServer.cpp ---------------------------------------------------------------------- diff --git a/tutorial/cpp/CppServer.cpp b/tutorial/cpp/CppServer.cpp index 84b79d4..6b22193 100644 --- a/tutorial/cpp/CppServer.cpp +++ b/tutorial/cpp/CppServer.cpp @@ -71,7 +71,7 @@ public: case Operation::DIVIDE: if (work.num2 == 0) { InvalidOperation io; - io.what = work.op; + io.whatOp = work.op; io.why = "Cannot divide by 0"; throw io; } @@ -79,7 +79,7 @@ public: break; default: InvalidOperation io; - io.what = work.op; + io.whatOp = work.op; io.why = "Invalid Operation"; throw io; } http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/d/server.d ---------------------------------------------------------------------- diff --git a/tutorial/d/server.d b/tutorial/d/server.d index d32b937..cbcedcc 100644 --- a/tutorial/d/server.d +++ b/tutorial/d/server.d @@ -62,7 +62,7 @@ class CalculatorHandler : Calculator { case Operation.DIVIDE: if (work.num2 == 0) { auto io = new InvalidOperation(); - io.what = work.op; + io.whatOp = work.op; io.why = "Cannot divide by 0"; throw io; } @@ -70,7 +70,7 @@ class CalculatorHandler : Calculator { break; default: auto io = new InvalidOperation(); - io.what = work.op; + io.whatOp = work.op; io.why = "Invalid Operation"; throw io; } http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/erl/server.erl ---------------------------------------------------------------------- diff --git a/tutorial/erl/server.erl b/tutorial/erl/server.erl index 4915606..f1e7357 100644 --- a/tutorial/erl/server.erl +++ b/tutorial/erl/server.erl @@ -44,12 +44,12 @@ calculate(Logid, Work) -> ?tutorial_Operation_MULTIPLY -> Num1 * Num2; ?tutorial_Operation_DIVIDE when Num2 == 0 -> - throw(#invalidOperation{what=Op, why="Cannot divide by 0"}); + throw(#invalidOperation{whatOp=Op, why="Cannot divide by 0"}); ?tutorial_Operation_DIVIDE -> Num1 div Num2; _Else -> - throw(#invalidOperation{what=Op, why="Invalid operation"}) + throw(#invalidOperation{whatOp=Op, why="Invalid operation"}) end. getStruct(Key) -> http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/haxe/src/CalculatorHandler.hx ---------------------------------------------------------------------- diff --git a/tutorial/haxe/src/CalculatorHandler.hx b/tutorial/haxe/src/CalculatorHandler.hx index 3376fb6..e9752db 100644 --- a/tutorial/haxe/src/CalculatorHandler.hx +++ b/tutorial/haxe/src/CalculatorHandler.hx @@ -67,7 +67,7 @@ class CalculatorHandler implements Calculator { if (work.num2 == 0) { var io = new InvalidOperation(); - io.what = work.op; + io.whatOp = work.op; io.why = "Cannot divide by 0"; throw io; } @@ -75,7 +75,7 @@ class CalculatorHandler implements Calculator { default: var io = new InvalidOperation(); - io.what = work.op; + io.whatOp = work.op; io.why = "Unknown operation"; throw io; } http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/hs/HaskellServer.hs ---------------------------------------------------------------------- diff --git a/tutorial/hs/HaskellServer.hs b/tutorial/hs/HaskellServer.hs index 77f1679..cfe1344 100644 --- a/tutorial/hs/HaskellServer.hs +++ b/tutorial/hs/HaskellServer.hs @@ -74,7 +74,7 @@ instance Calculator_Iface CalculatorHandler where if num2 work == 0 then throw $ InvalidOperation { - invalidOperation_what = fromIntegral $ fromEnum $ op work, + invalidOperation_whatOp = fromIntegral $ fromEnum $ op work, invalidOperation_why = "Cannot divide by 0" } else http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/java/src/CalculatorHandler.java ---------------------------------------------------------------------- diff --git a/tutorial/java/src/CalculatorHandler.java b/tutorial/java/src/CalculatorHandler.java index 4216be5..92944b0 100644 --- a/tutorial/java/src/CalculatorHandler.java +++ b/tutorial/java/src/CalculatorHandler.java @@ -58,7 +58,7 @@ public class CalculatorHandler implements Calculator.Iface { case DIVIDE: if (work.num2 == 0) { InvalidOperation io = new InvalidOperation(); - io.what = work.op.getValue(); + io.whatOp = work.op.getValue(); io.why = "Cannot divide by 0"; throw io; } @@ -66,7 +66,7 @@ public class CalculatorHandler implements Calculator.Iface { break; default: InvalidOperation io = new InvalidOperation(); - io.what = work.op.getValue(); + io.whatOp = work.op.getValue(); io.why = "Unknown operation"; throw io; } http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/nodejs/NodeServer.js ---------------------------------------------------------------------- diff --git a/tutorial/nodejs/NodeServer.js b/tutorial/nodejs/NodeServer.js index ba36105..55d3817 100644 --- a/tutorial/nodejs/NodeServer.js +++ b/tutorial/nodejs/NodeServer.js @@ -48,7 +48,7 @@ var server = thrift.createServer(Calculator, { } else if (work.op === ttypes.Operation.DIVIDE) { if (work.num2 === 0) { var x = new ttypes.InvalidOperation(); - x.what = work.op; + x.whatOp = work.op; x.why = 'Cannot divide by 0'; result(x); return; @@ -56,7 +56,7 @@ var server = thrift.createServer(Calculator, { val = work.num1 / work.num2; } else { var x = new ttypes.InvalidOperation(); - x.what = work.op; + x.whatOp = work.op; x.why = 'Invalid operation'; result(x); return; http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/nodejs/NodeServerPromise.js ---------------------------------------------------------------------- diff --git a/tutorial/nodejs/NodeServerPromise.js b/tutorial/nodejs/NodeServerPromise.js index 4fd0a35..bff287b 100644 --- a/tutorial/nodejs/NodeServerPromise.js +++ b/tutorial/nodejs/NodeServerPromise.js @@ -47,14 +47,14 @@ var server = thrift.createServer(Calculator, { } else if (work.op === ttypes.Operation.DIVIDE) { if (work.num2 === 0) { var x = new ttypes.InvalidOperation(); - x.what = work.op; + x.whatOp = work.op; x.why = 'Cannot divide by 0'; throw x; } val = work.num1 / work.num2; } else { var x = new ttypes.InvalidOperation(); - x.what = work.op; + x.whatOp = work.op; x.why = 'Invalid operation'; throw x; } http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/ocaml/CalcServer.ml ---------------------------------------------------------------------- diff --git a/tutorial/ocaml/CalcServer.ml b/tutorial/ocaml/CalcServer.ml index 24d7d03..b5facb7 100755 --- a/tutorial/ocaml/CalcServer.ml +++ b/tutorial/ocaml/CalcServer.ml @@ -49,7 +49,7 @@ object (self) | Operation.DIVIDE -> if w#grab_num2 = Int32.zero then let io = new invalidOperation in - io#set_what (Operation.to_i w#grab_op) ; + io#set_whatOp (Operation.to_i w#grab_op) ; io#set_why "Cannot divide by 0" ; raise (InvalidOperation io) else http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/perl/PerlServer.pl ---------------------------------------------------------------------- diff --git a/tutorial/perl/PerlServer.pl b/tutorial/perl/PerlServer.pl index a40ec69..adec978 100644 --- a/tutorial/perl/PerlServer.pl +++ b/tutorial/perl/PerlServer.pl @@ -68,14 +68,14 @@ sub calculate if ($num2 == 0) { my $x = new tutorial::InvalidOperation; - $x->what($op); + $x->whatOp($op); $x->why('Cannot divide by 0'); die $x; } $val = $num1 / $num2; } else { my $x = new tutorial::InvalidOperation; - $x->what($op); + $x->whatOp($op); $x->why('Invalid operation'); die $x; } http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/php/PhpServer.php ---------------------------------------------------------------------- diff --git a/tutorial/php/PhpServer.php b/tutorial/php/PhpServer.php index 4af70a4..22ae43e 100755 --- a/tutorial/php/PhpServer.php +++ b/tutorial/php/PhpServer.php @@ -79,7 +79,7 @@ class CalculatorHandler implements \tutorial\CalculatorIf { case \tutorial\Operation::DIVIDE: if ($w->num2 == 0) { $io = new \tutorial\InvalidOperation(); - $io->what = $w->op; + $io->whatOp = $w->op; $io->why = "Cannot divide by 0"; throw $io; } @@ -87,7 +87,7 @@ class CalculatorHandler implements \tutorial\CalculatorIf { break; default: $io = new \tutorial\InvalidOperation(); - $io->what = $w->op; + $io->whatOp = $w->op; $io->why = "Invalid Operation"; throw $io; } http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/py.tornado/PythonServer.py ---------------------------------------------------------------------- diff --git a/tutorial/py.tornado/PythonServer.py b/tutorial/py.tornado/PythonServer.py index 52932ff..7a34107 100755 --- a/tutorial/py.tornado/PythonServer.py +++ b/tutorial/py.tornado/PythonServer.py @@ -62,13 +62,13 @@ class CalculatorHandler(object): elif work.op == Operation.DIVIDE: if work.num2 == 0: x = InvalidOperation() - x.what = work.op + x.whatOp = work.op x.why = "Cannot divide by 0" raise x val = work.num1 / work.num2 else: x = InvalidOperation() - x.what = work.op + x.whatOp = work.op x.why = "Invalid operation" raise x http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/py.twisted/PythonServer.py ---------------------------------------------------------------------- diff --git a/tutorial/py.twisted/PythonServer.py b/tutorial/py.twisted/PythonServer.py index f023cac..227f6d4 100755 --- a/tutorial/py.twisted/PythonServer.py +++ b/tutorial/py.twisted/PythonServer.py @@ -59,13 +59,13 @@ class CalculatorHandler: elif work.op == Operation.DIVIDE: if work.num2 == 0: x = InvalidOperation() - x.what = work.op + x.whatOp = work.op x.why = 'Cannot divide by 0' raise x val = work.num1 / work.num2 else: x = InvalidOperation() - x.what = work.op + x.whatOp = work.op x.why = 'Invalid operation' raise x http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/py/PythonServer.py ---------------------------------------------------------------------- diff --git a/tutorial/py/PythonServer.py b/tutorial/py/PythonServer.py index 014a12e..533b0ea 100755 --- a/tutorial/py/PythonServer.py +++ b/tutorial/py/PythonServer.py @@ -56,13 +56,13 @@ class CalculatorHandler: elif work.op == Operation.DIVIDE: if work.num2 == 0: x = InvalidOperation() - x.what = work.op + x.whatOp = work.op x.why = 'Cannot divide by 0' raise x val = work.num1 / work.num2 else: x = InvalidOperation() - x.what = work.op + x.whatOp = work.op x.why = 'Invalid operation' raise x http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/rb/RubyServer.rb ---------------------------------------------------------------------- diff --git a/tutorial/rb/RubyServer.rb b/tutorial/rb/RubyServer.rb index 22cec31..1d707d7 100755 --- a/tutorial/rb/RubyServer.rb +++ b/tutorial/rb/RubyServer.rb @@ -52,14 +52,14 @@ class CalculatorHandler elsif work.op == Operation::DIVIDE if work.num2 == 0 x = InvalidOperation.new() - x.what = work.op + x.whatOp = work.op x.why = "Cannot divide by 0" raise x end val = work.num1 / work.num2 else x = InvalidOperation.new() - x.what = work.op + x.whatOp = work.op x.why = "Invalid operation" raise x end http://git-wip-us.apache.org/repos/asf/thrift/blob/3b115dfa/tutorial/tutorial.thrift ---------------------------------------------------------------------- diff --git a/tutorial/tutorial.thrift b/tutorial/tutorial.thrift index c8710d4..571ab8e 100644 --- a/tutorial/tutorial.thrift +++ b/tutorial/tutorial.thrift @@ -113,7 +113,7 @@ struct Work { * Structs can also be exceptions, if they are nasty. */ exception InvalidOperation { - 1: i32 what, + 1: i32 whatOp, 2: string why }
