diff options
10 files changed, 472 insertions, 0 deletions
diff --git a/TAO/bin/tao_orb_tests.lst b/TAO/bin/tao_orb_tests.lst index 67cf0476eec..068e5a28e57 100644 --- a/TAO/bin/tao_orb_tests.lst +++ b/TAO/bin/tao_orb_tests.lst @@ -434,6 +434,7 @@ TAO/tests/Native_Exceptions/run_test.pl: TAO/tests/Servant_To_Reference_Test/run_test.pl: !MINIMUM !CORBA_E_COMPACT !CORBA_E_MICRO !ST TAO/tests/Sequence_Unit_Tests/run_test.pl: TAO/tests/Typedef_String_Array/run_test.pl: +TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl: !FIXED_BUGS_ONLY TAO/tests/GIOP_Fragments/PMB_With_Fragments/run_test.pl: !CORBA_E_MICRO TAO/tests/CodeSets/simple/run_test.pl: !GIOP10 !STATIC TAO/tests/Hang_Shutdown/run_test.pl: !ST !ACE_FOR_TAO diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore b/TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore new file mode 100644 index 00000000000..9ec82bc74d9 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/.gitignore @@ -0,0 +1,9 @@ +.obj +.depend.Echo_Client +.depend.Echo_Server +.depend.echo_idl +.depend.echo_idl_Idl1 +server_log.txt +client_log.txt +client +server diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Big_String_Sequence.mpc b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Big_String_Sequence.mpc new file mode 100644 index 00000000000..155304588b1 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Big_String_Sequence.mpc @@ -0,0 +1,31 @@ +// -*- MPC -*- +project(*idl): taoidldefaults { + IDL_Files { + Echo.idl + } + custom_only = 1 +} + +project(*Server): taoserver { + exename = server + after += *idl + Source_Files { + Echo_i.cpp + server.cpp + EchoS.cpp + EchoC.cpp + } + IDL_Files { + } +} + +project(*Client): taoclient { + exename = client + after += *idl + Source_Files { + client.cpp + EchoC.cpp + } + IDL_Files { + } +} diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo.idl b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo.idl new file mode 100644 index 00000000000..e871c7a5f4e --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo.idl @@ -0,0 +1,13 @@ +interface Echo +{ + // Defines an interface that encapsulates an operation that returns + // a string sequence, or a wstring sequence, respectively. + + typedef sequence<string> List; + typedef sequence<wstring> WList; + + List return_list (); + WList return_wlist (); + + oneway void shutdown (); +}; diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp new file mode 100644 index 00000000000..04f187eb814 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.cpp @@ -0,0 +1,79 @@ +#include "Echo_i.h" + +constexpr size_t BIG_LENGTH = 4 * 1024; + +// Constructor. + +Echo_i::Echo_i (CORBA::ORB_ptr o) + : orb_(o) +{ +} + +// Return a list of strings. +Echo::List * +Echo_i::return_list () +{ + Echo::List_var list; + + { + Echo::List *tmp {}; + ACE_NEW_RETURN (tmp, + Echo::List (2), + {}); + list = tmp; + } + + list->length (2); + + // Just do something to get a 'big' list of strings. + CORBA::Char big[BIG_LENGTH + 1]; + for (size_t i = 0; i < BIG_LENGTH; ++i) + big[i] = 'A'; + big[BIG_LENGTH] = 0; + list[CORBA::ULong(0)] = CORBA::string_dup(big); + list[CORBA::ULong(1)] = CORBA::string_dup("Hello World"); + + return list._retn (); +} + +Echo::WList * +Echo_i::return_wlist () +{ + Echo::WList_var list; + + { + Echo::WList *tmp {}; + ACE_NEW_RETURN (tmp, + Echo::WList (2), + {}); + list = tmp; + } + + list->length (2); + + // Just do something to get a 'big' list of wide strings. + CORBA::WChar big[BIG_LENGTH + 1]; + for (size_t i = 0; i < BIG_LENGTH; ++i) + big[i] = 'A'; + big[BIG_LENGTH] = 0; + CORBA::WChar small[17 + 1]; + for (size_t i = 0; i < 17; ++i) + small[i] = 'B'; + small[17] = 0; + list[CORBA::ULong(0)] = CORBA::wstring_dup(big); + list[CORBA::ULong(1)] = CORBA::wstring_dup(small); + + return list._retn (); +} + +// Shutdown the server application. + +void +Echo_i::shutdown () +{ + ACE_DEBUG ((LM_DEBUG, + ACE_TEXT ("\nThe echo server is shutting down\n"))); + + // Instruct the ORB to shutdown. + this->orb_->shutdown (); +} diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.h b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.h new file mode 100644 index 00000000000..3be035a6eee --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/Echo_i.h @@ -0,0 +1,47 @@ +// -*- C++ -*- + +//============================================================================= +/** + * @file Echo_i.h + * + * This class implements the Echo IDL interface. + * + */ +//============================================================================= + + +#ifndef ECHO_I_H +#define ECHO_I_H + +#include "EchoS.h" + +/** + * @class Echo_i + * + * @brief Echo Object Implementation + * + */ +class Echo_i : public POA_Echo +{ +public: + /// Constructor. + Echo_i (CORBA::ORB_ptr o); + + /// Destructor. + ~Echo_i () override = default; + + /// Return the result sequences to the cllient. + Echo::List *return_list () override; + Echo::WList *return_wlist () override; + + /// Shutdown the server. + void shutdown () override; + +private: + /// ORB pointer. + CORBA::ORB_var orb_; + + void operator= (const Echo_i&) = delete; +}; + +#endif /* ECHO_I_H */ diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/README.md b/TAO/tests/GIOP_Fragments/Big_String_Sequence/README.md new file mode 100644 index 00000000000..55620b45305 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/README.md @@ -0,0 +1,10 @@ +# TAO GIOP Fragmentation Bug +## Reproduces a bug when GIOP fragmentation is used + +The server returns a string sequence with two elements, the first is a +long 4kB string with repeating character 'A', the second element is +the string "Hello World". If one removes the command line parameters +`-ORBMaxMessageSize 1024` from `run_test.pl` everything +works as expected, but with these settings, which cause GIOP +fragmentation, the client receives an empty string as the second +element of the sequence. diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp new file mode 100644 index 00000000000..21ef8c8008b --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/client.cpp @@ -0,0 +1,107 @@ +#include "EchoC.h" +#include "ace/Get_Opt.h" +#include <cstring> + +const ACE_TCHAR *ior = ACE_TEXT ("file://test.ior"); + +int parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("f:")); + int c; + + while ((c = get_opts ()) != -1) + switch (c) + { + case 'f': + ior = get_opts.opt_arg (); + break; + + case '?': + default: + ACE_ERROR_RETURN ((LM_ERROR, + "usage: %s " + "-f <ior> " + "\n", + argv [0]), + -1); + } + // Indicates successful parsing of the command line + return 0; +} + +int +ACE_TMAIN(int argc, ACE_TCHAR *argv[]) +{ + try + { + CORBA::ORB_var orb = CORBA::ORB_init (argc, argv); + + if (parse_args (argc, argv) != 0) + return -1; + + CORBA::Object_var tmp = orb->string_to_object(ior); + + Echo_var echo = Echo::_narrow(tmp.in ()); + + if (CORBA::is_nil (echo.in ())) + { + ACE_ERROR_RETURN ((LM_ERROR, + "Nil Echo reference <%s>\n", + ior), + -1); + } + + Echo::List_var list = echo->return_list(); + + ACE_DEBUG ((LM_DEBUG, + "Received list of length %u\n", + list->length())); + if (list->length() != 2) + { + ACE_ERROR_RETURN ((LM_ERROR, "Expected length 2\n"), -1); + } + const char* value = (*list)[0].in(); + size_t length = std::strlen(value); + ACE_DEBUG ((LM_DEBUG, + "First element has length %u\n", + length)); + for (size_t n = 0; n < length; ++n) + { + if (value[n] != 'A') + { + ACE_ERROR_RETURN ((LM_ERROR, + "Character at position %u should be 'A'," + " but is '%c'\n", value[n]), -1); + } + } + value = (*list)[1].in(); + length = std::strlen(value); + ACE_DEBUG ((LM_DEBUG, + "Second element has length %u, value: <%C>\n", + length, value)); + if (strcmp(value, "Hello World") != 0) + { + ACE_ERROR_RETURN ((LM_ERROR, "Expected \"Hello World\""), -1); + } + + Echo::WList_var wlist = echo->return_wlist(); + + ACE_DEBUG ((LM_DEBUG, + "Received wide list of length %u\n", + wlist->length())); + if (wlist->length() != 2) + { + ACE_ERROR_RETURN ((LM_ERROR, "Expected length 2\n"), -1); + } + + echo->shutdown (); + orb->destroy (); + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ("Exception caught:"); + return 1; + } + + return 0; +} diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl b/TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl new file mode 100755 index 00000000000..329c2ea3ff3 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/run_test.pl @@ -0,0 +1,76 @@ +eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' + & eval 'exec perl -S $0 $argv:q' + if 0; + +# -*- perl -*- + +use lib "$ENV{ACE_ROOT}/bin"; +use PerlACE::TestTarget; + +$status = 0; +$debug_level = '0'; + +foreach $i (@ARGV) { + if ($i eq '-debug') { + $debug_level = '10'; + } +} + +my $server = PerlACE::TestTarget::create_target (1) || die "Create target 1 failed\n"; +my $client = PerlACE::TestTarget::create_target (2) || die "Create target 2 failed\n"; + +my $iorbase = "server.ior"; +my $server_iorfile = $server->LocalFile ($iorbase); +my $client_iorfile = $client->LocalFile ($iorbase); + +$server->DeleteFile($iorbase); +$client->DeleteFile($iorbase); + +$SV = $server->CreateProcess ("server", "-ORBMaxMessageSize 1024 -ORBdebuglevel $debug_level -o $server_iorfile"); +$CL = $client->CreateProcess ("client", "-ORBdebuglevel $debug_level -f file://$client_iorfile"); +$server_status = $SV->Spawn (); + +if ($server_status != 0) { + print STDERR "ERROR: server returned $server_status\n"; + exit 1; +} + +if ($server->WaitForFileTimed ($iorbase, + $server->ProcessStartWaitInterval()) == -1) { + print STDERR "ERROR: cannot find file <$server_iorfile>\n"; + $SV->Kill (); $SV->TimedWait (1); + exit 1; +} + +if ($server->GetFile ($iorbase) == -1) { + print STDERR "ERROR: cannot retrieve file <$server_iorfile>\n"; + $SV->Kill (); $SV->TimedWait (1); + exit 1; +} +if ($client->PutFile ($iorbase) == -1) { + print STDERR "ERROR: cannot set file <$client_iorfile>\n"; + $SV->Kill (); $SV->TimedWait (1); + exit 1; +} + +$client_status = $CL->SpawnWaitKill ($client->ProcessStartWaitInterval()); + +if ($client_status != 0) { + print STDERR "ERROR: client returned $client_status\n"; + $status = 1; +} + +$server_status = $SV->WaitKill ($server->ProcessStopWaitInterval()); + +if ($server_status != 0) { + print STDERR "ERROR: server returned $server_status\n"; + $status = 1; +} + +$server->GetStderrLog(); +$client->GetStderrLog(); + +$server->DeleteFile($server_iorfile); +$client->DeleteFile($client_iorfile); + +exit $status; diff --git a/TAO/tests/GIOP_Fragments/Big_String_Sequence/server.cpp b/TAO/tests/GIOP_Fragments/Big_String_Sequence/server.cpp new file mode 100644 index 00000000000..51e4b5df7d7 --- /dev/null +++ b/TAO/tests/GIOP_Fragments/Big_String_Sequence/server.cpp @@ -0,0 +1,99 @@ +#include "Echo_i.h" +#include "ace/Get_Opt.h" +#include "ace/OS_NS_stdio.h" + +const ACE_TCHAR *ior_output_file = ACE_TEXT ("test.ior"); + +int +parse_args (int argc, ACE_TCHAR *argv[]) +{ + ACE_Get_Opt get_opts (argc, argv, ACE_TEXT("o:")); + int c; + + while ((c = get_opts ()) != -1) + switch (c) + { + case 'o': + ior_output_file = get_opts.opt_arg (); + break; + + case '?': + default: + ACE_ERROR_RETURN ((LM_ERROR, + "usage: %s " + "-o <iorfile>" + "\n", + argv [0]), + -1); + } + // Indicates successful parsing of the command line + return 0; +} + +int +ACE_TMAIN(int argc, ACE_TCHAR *argv[]) +{ + try + { + CORBA::ORB_var orb = + CORBA::ORB_init (argc, argv); + + CORBA::Object_var poa_object = + orb->resolve_initial_references("RootPOA"); + + PortableServer::POA_var root_poa = + PortableServer::POA::_narrow (poa_object.in ()); + + if (CORBA::is_nil (root_poa.in ())) + ACE_ERROR_RETURN ((LM_ERROR, + " (%P|%t) Panic: nil RootPOA\n"), + 1); + + PortableServer::POAManager_var poa_manager = root_poa->the_POAManager (); + + if (parse_args (argc, argv) != 0) + return 1; + + Echo_i *echo_impl = 0; + ACE_NEW_RETURN (echo_impl, + Echo_i (orb.in ()), + 1); + PortableServer::ServantBase_var owner_transfer(echo_impl); + + PortableServer::ObjectId_var id = + root_poa->activate_object (echo_impl); + + CORBA::Object_var object = root_poa->id_to_reference (id.in ()); + + Echo_var echo = Echo::_narrow (object.in ()); + + CORBA::String_var ior = orb->object_to_string (echo.in ()); + + // Output the IOR to the <ior_output_file> + FILE* output_file = ACE_OS::fopen (ior_output_file, "w"); + if (output_file == 0) + ACE_ERROR_RETURN ((LM_ERROR, + "Cannot open output file for writing IOR: %s\n", + ior_output_file), + 1); + ACE_OS::fprintf (output_file, "%s", ior.in ()); + ACE_OS::fclose (output_file); + + poa_manager->activate (); + + orb->run (); + + ACE_DEBUG ((LM_DEBUG, "(%P|%t) server - event loop finished\n")); + + root_poa->destroy (true, true); + + orb->destroy (); + } + catch (const CORBA::Exception& ex) + { + ex._tao_print_exception ("Exception caught:"); + return 1; + } + + return 0; +} |